├── config ├── adb-restore.sh ├── adb-backup.sh ├── backup.sh ├── README.md └── restore.sh /config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | localtmpdir="/tmp" 4 | localdatadir="$localtmpdir/amu-backup" 5 | devtmpdir="/sdcard" 6 | devdatadir="$devtmpdir/amu-backup" 7 | 8 | -------------------------------------------------------------------------------- /adb-restore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . $(dirname $0)/config 4 | 5 | set -e 6 | 7 | adb shell su -c \'rm -rf $devdatadir\' 8 | adb push $localdatadir/ $devdatadir/ 9 | adb push $(dirname $0)/restore.sh $devtmpdir/ 10 | adb push $(dirname $0)/config $devtmpdir/ 11 | adb shell su -c \'sh $devtmpdir/restore.sh $*\' 12 | adb shell su -c \'rm -rf $devdatadir\' 13 | adb shell rm -f $devtmpdir/restore.sh 14 | adb shell rm -f $devtmpdir/config 15 | -------------------------------------------------------------------------------- /adb-backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . $(dirname $0)/config 4 | 5 | set -e 6 | 7 | rm -rf $localdatadir; 8 | adb shell su -c \'rm -rf $devdatadir\' 9 | adb push $(dirname $0)/backup.sh $devtmpdir/ 10 | adb push $(dirname $0)/config $devtmpdir/ 11 | adb shell su -c \'sh $devtmpdir/backup.sh $*\' 12 | adb pull $devdatadir $localdatadir 13 | adb shell su -c \'rm -rf $devdatadir\' 14 | adb shell rm -f $devtmpdir/backup.sh 15 | adb shell rm -f $devtmpdir/config 16 | -------------------------------------------------------------------------------- /backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | . $(dirname $0)/config 6 | 7 | uid=$1 8 | shift 9 | pkg=$1 10 | 11 | if [ -z "$uid" -o -z "$pkg" ]; then 12 | echo "Usage $0 " 13 | exit 0 14 | fi 15 | 16 | 17 | base="$devdatadir" 18 | mkdir -p $base/{apks,data} 19 | 20 | cd /data 21 | pkgs="$*" 22 | uids="$uid" 23 | alluids=0 24 | 25 | # Backup all installed packages? 26 | if [ "$pkg" = "all" ]; then 27 | pkgs="$(pm list packages | cut -f2 -d':')" 28 | fi 29 | 30 | if [ "$uid" = "all" ]; then 31 | alluids=1 32 | uids="$(pm list users | grep 'UserInfo' | cut -f1 -d':' | cut -f2 -d'{')" 33 | fi 34 | 35 | for uid in $uids; do 36 | echo "Creating backup for uid $uid.." 37 | mkdir -p $base/data/$uid 38 | for pkg in $pkgs; do 39 | if [ -f /data/app/$pkg-*/base.apk ]; then 40 | echo " Backing up pkg $pkg.." 41 | if [ ! -f "$base/apks/$pkg.apk" ]; then 42 | echo " Backing up apk.." 43 | cp /data/app/$pkg-*/base.apk $base/apks/$pkg.apk 44 | echo " done." 45 | else 46 | echo " apk already backed up." 47 | fi 48 | if [ ! -z "$(pm list package -e --user $uid $pkg)" ]; then 49 | if [ -d "user/$uid/$pkg" ]; then 50 | echo " Backing up userdata.." 51 | tar c -C user/$uid -f $base/data/$uid/$pkg-user.tar $pkg 52 | echo " done." 53 | fi 54 | if [ -d "media/$uid/Android/data/$pkg" ]; then 55 | echo " Backing up media.." 56 | tar c -C media/$uid/Android/data -f $base/data/$uid/$pkg-media.tar $pkg 57 | echo " done." 58 | fi 59 | else 60 | echo " pkg $pkg is not enabled for user $uid" 61 | touch $base/data/$uid/$pkg.disabled 62 | fi 63 | echo " done." 64 | fi 65 | done 66 | echo "done." 67 | if [ -f "/data/system/users/$uid/accounts.db" ]; then 68 | echo "Creating backup of accounts.db .." 69 | cp /data/system/users/$uid/accounts.db $base/data/$uid/ 70 | echo "done." 71 | fi 72 | done 73 | if [ -f "/data/system/sync/accounts.xml" ]; then 74 | echo "Creating backup of accounts.xml .." 75 | cp /data/system/sync/accounts.xml $base/data/ 76 | echo "done." 77 | fi 78 | 79 | find $base 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cluk33/android-multiuser-backup 2 | 3 | **a set of shell scripts to backup and restore apps and data for multiuser android devices** 4 | 5 | ## Motivation 6 | I spend hours to find a way to copy all data from all useraccounts from my old tablet to the new one. 7 | Neither adb backup, nor Titanium Backup or oandbackup worked correctly. 8 | 9 | Titanium need supersu for every user and does not backup data for users which 10 | are not the device owner (userid!=0). 11 | 12 | Oandbackup also needs supersu. It backs up data from /data/user but after running 13 | a restore the restored apps crash because of permission problems in /data/user. 14 | The directory and file ownership and permissions in /data/user are restored 15 | correctly but the selinux context information is missing which makes the files 16 | inaccessible by the app process. You can see a lot of 'permission denied' errors 17 | in the logcat. 18 | 19 | ## Prerequisites 20 | The shell scripts in this repo require 21 | - a rooted device, 22 | - a working adb connection and 23 | - su working in the adb shell. 24 | 25 | ## Backup 26 | After cloning the repo you could simply run: 27 | ```bash 28 | adb-backup.sh [ ..] 29 | ``` 30 | eg: 31 | ```bash 32 | adb-backup.sh 12 org.mozilla.firefox com.foo.bar 33 | ``` 34 | ### backup all user and/or all apps 35 | Both parameters uid / pkg allow for the special token 'all'. This will either 36 | backup the data for all users or for all apps (from one user). 37 | eg backup all user's firefox data: 38 | ```bash 39 | adb-backup.sh all org.mozilla.firefox 40 | ``` 41 | eg backup all apps from all users: 42 | ```bash 43 | adb-backup.sh all all 44 | ``` 45 | ## Restore 46 | ```bash 47 | adb-restore.sh [ ..] 48 | ``` 49 | 50 | eg: 51 | ```bash 52 | adb-restore.sh 12 org.mozilla.firefox com.foo.bar 53 | ``` 54 | ### restore all users and/or all apps 55 | Both parameters uid / pkg allow for the special token 'all'. This will either 56 | restore the data for all users or for all apps (from one user). 57 | If you try to restore 'all' apps the data from all apps which have been backed up 58 | before is restored. 59 | eg restore all user's firefox data: 60 | ```bash 61 | adb-restore.sh all org.mozilla.firefox 62 | ``` 63 | eg restore all apps from all users: 64 | ```bash 65 | adb-restore.sh all all 66 | ``` 67 | -------------------------------------------------------------------------------- /restore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | . $(dirname $0)/config 6 | 7 | uid=$1 8 | shift 9 | pkg=$1 10 | 11 | if [ -z "$uid" -o -z "$pkg" ]; then 12 | echo "Usage $0 " 13 | exit 0 14 | fi 15 | 16 | 17 | base="$devdatadir" 18 | 19 | cd /data 20 | pkgs="$*" 21 | uids=$uid 22 | 23 | # Backup all installed packages? 24 | if [ "$pkg" = "all" ]; then 25 | pkgfiles="$(cd $devdatadir/apks; ls *.apk)" 26 | pkgs="" 27 | for file in $pkgfiles; do 28 | pkgs="$pkgs ${file%\.apk}" 29 | done 30 | fi 31 | 32 | if [ "$uid" = "all" ]; then 33 | uids="$(cd $devdatadir/data; ls | grep '^[0-9]*$')" 34 | fi 35 | 36 | for uid in $uids; do 37 | echo "Restoring backup for uid $uid.." 38 | for pkg in $pkgs; do 39 | [ -z "$pkg" ] && ( echo "Missing pkg"; exit 1) 40 | echo " Restoring pkg $pkg.." 41 | if [ -f "$base/apks/$pkg.apk" ]; then 42 | if [ -z "$(pm list package $pkg)" ]; then 43 | echo " Installing pkg.." 44 | pm install $base/apks/$pkg.apk >/dev/null 45 | echo " done." 46 | else 47 | echo " pkg already installed.." 48 | fi 49 | if [ -f "$base/data/$uid/$pkg.disabled" ]; then 50 | echo " Disabling pkg.." 51 | pm disable --user $uid $pkg >/dev/null 52 | echo " done." 53 | else 54 | echo " Enabling pkg.." 55 | pm enable --user $uid $pkg >/dev/null 56 | echo " done." 57 | fi 58 | fi 59 | if [ -f "$base/data/$uid/$pkg-user.tar" ]; then 60 | echo " Getting uid/gid and secontext.." 61 | secontext=$(ls -dZ user/$uid/$pkg | cut -f1 -d' ') 62 | user=$(ls -dl user/$uid/$pkg | cut -f3 -d' ') 63 | group=$(ls -dl user/$uid/$pkg | cut -f4 -d' ') 64 | echo " done." 65 | echo " Restoring userdata.." 66 | rm -rf user/$uid/$pkg 67 | tar x -C user/$uid -f $base/data/$uid/$pkg-user.tar $pkg 68 | echo " done." 69 | echo " Restoring ownership.." 70 | chown -R $user:$group user/$uid/$pkg 71 | echo " done." 72 | echo " Restoring secontext.." 73 | find user/$uid/$pkg -exec chcon $secontext {} \; 74 | echo " done." 75 | fi 76 | if [ -f "$base/data/$uid/$pkg-media.tar" ]; then 77 | echo " Restoring media.." 78 | rm -rf media/$uid/Android/data/$pkg 79 | tar x -C media/$uid/Android/data -f $base/data/$uid/$pkg-media.tar $pkg 80 | echo " done." 81 | fi 82 | echo " done." 83 | done 84 | echo "done." 85 | done 86 | --------------------------------------------------------------------------------