|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
--- |
|
|
|
|
title: Syncing files from Android to GNU/Linux |
|
|
|
|
tags: [android, rsync, sshfs, ssh, sync, backup, bash] |
|
|
|
|
updated: 2019-02-15 11:20 |
|
|
|
|
updated: 2019-06-28 12:08 |
|
|
|
|
description: Syncronization of files from Android to a GNU/Linux system |
|
|
|
|
--- |
|
|
|
|
|
|
|
|
@ -12,6 +12,8 @@ but unfortunately the tools to do a clean job have always been inadeguate.
|
|
|
|
|
Also, I certainly didn't want to rely on third party services such as |
|
|
|
|
Dropbox, Google, etc... |
|
|
|
|
|
|
|
|
|
<!--more--> |
|
|
|
|
|
|
|
|
|
The first solution was to use bluetooth with an APP I can't even remember the |
|
|
|
|
name of. The problem was its slow speed and non-secureness. |
|
|
|
|
|
|
|
|
@ -31,46 +33,29 @@ server. The advantages of SFTP instead of using other systems are:
|
|
|
|
|
|
|
|
|
|
# Steps |
|
|
|
|
|
|
|
|
|
1. Set a fixed IP address for the phone. |
|
|
|
|
2. Download the [APP from Fdroid](https://f-droid.org/en/packages/org.primftpd/). |
|
|
|
|
3. Open the APP and choose a username and password in the settings menu. |
|
|
|
|
4. Start the server and tap `yes` when asked for key generation. |
|
|
|
|
5. Install [SSHFS](http://github.com/libfuse/sshfs) and [Rsync](https://rsync.samba.org/) on the target computer. |
|
|
|
|
6. Adapt the following script I have written for the purpose: |
|
|
|
|
- Set a fixed IP address for the phone. |
|
|
|
|
- Download the [APP from Fdroid](https://f-droid.org/en/packages/org.primftpd/). |
|
|
|
|
- Open the APP and choose a username and password in the settings menu. |
|
|
|
|
- Start the server and tap `yes` when asked for key generation. |
|
|
|
|
- Install [SSHFS](http://github.com/libfuse/sshfs) and [Rsync](https://rsync.samba.org/) on the target computer. |
|
|
|
|
- Adapt the following script I have written for the purpose: |
|
|
|
|
|
|
|
|
|
```shell |
|
|
|
|
# Get the value from argc. |
|
|
|
|
ALIAS="$1" |
|
|
|
|
|
|
|
|
|
# checksum option because it avoids problems with partial file transfers. |
|
|
|
|
# Archive without keeping original user and group file attributes. |
|
|
|
|
RSYNC_MAIN_OPTS='--checksum -rltD' |
|
|
|
|
|
|
|
|
|
# Set the devices variables here. |
|
|
|
|
# Just edit this part and you should be good to go. |
|
|
|
|
if [ "${ALIAS}" = "user0" ]; then |
|
|
|
|
USERNAME='username0' |
|
|
|
|
PASSWORD='password0' |
|
|
|
|
ADDRESS='1.2.3.4' |
|
|
|
|
PORT='65432' |
|
|
|
|
MOUNT_DIR='/home/user/mountpoints/user0' |
|
|
|
|
DST_DIR='/home/user/backup/user0' |
|
|
|
|
AKA='user 0' |
|
|
|
|
elif [ "${ALIAS}" = "user1" ]; then |
|
|
|
|
USERNAME='username1' |
|
|
|
|
PASSWORD='password1' |
|
|
|
|
ADDRESS='5.6.7.8' |
|
|
|
|
PORT='65432' |
|
|
|
|
MOUNT_DIR='/home/user/mountpoints/user1' |
|
|
|
|
DST_DIR='/home/user/backup/user1' |
|
|
|
|
AKA='user 1' |
|
|
|
|
elif [ "${ALIAS}" = '' ]; then |
|
|
|
|
printf "unspecified device" 2>&1 |
|
|
|
|
exit 1 |
|
|
|
|
else |
|
|
|
|
printf "unkown device" 2>&1 |
|
|
|
|
exit 1 |
|
|
|
|
fi |
|
|
|
|
#!/usr/bin/env bash |
|
|
|
|
|
|
|
|
|
# The full path of the configuration file |
|
|
|
|
CONFIGURATION="${1}" |
|
|
|
|
|
|
|
|
|
{ command -V rsync && command -V bash && command -V mail \ |
|
|
|
|
&& command -V printf && command -V sync; command -V fusermount3; } \ |
|
|
|
|
|| exit 1 |
|
|
|
|
{ [ ! -f "${CONFIGURATION}" ]; } \ |
|
|
|
|
&& printf "%s\n" 'check configuration file' 2>&1 && exit 1 |
|
|
|
|
|
|
|
|
|
# See https://gist.github.com/mfellner/5743990 |
|
|
|
|
RSYNC_MAIN_OPTS='-rv --size-only --no-group --no-owner --no-perms --no-times --whole-file --inplace' |
|
|
|
|
|
|
|
|
|
START=$(date +%s) |
|
|
|
|
|
|
|
|
|
# Mount only if not already mounted. |
|
|
|
|
exists_mount="$(mount | grep ""${USERNAME}"@"${ADDRESS}":")" |
|
|
|
@ -81,31 +66,66 @@ fi
|
|
|
|
|
# Might not be mounted if device not in range or if its server is offline. |
|
|
|
|
exists_mount="$(mount | grep ""${USERNAME}"@"${ADDRESS}":")" |
|
|
|
|
if [ -z "${exists_mount}" ]; then |
|
|
|
|
echo ""${AKA}" not connected" |
|
|
|
|
echo ""${ALIAS}" not connected" |
|
|
|
|
exit 1 |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
rsync "${RSYNC_MAIN_OPTS}" "${MOUNT_DIR}"/* "${DST_DIR}" |
|
|
|
|
ret_rsync=$? |
|
|
|
|
# You may want to send mails or write to log files instead of a simple print |
|
|
|
|
# operation. |
|
|
|
|
if [ "$ret_rsync" -ne 0 ]; then |
|
|
|
|
echo "FAILED "${AKA}" ret_rsync=$ret_rsync" |
|
|
|
|
ret_rsync=${?} |
|
|
|
|
sync |
|
|
|
|
fusermount3 -u "${MOUNT_DIR}" |
|
|
|
|
|
|
|
|
|
FINISH=$(date +%s) |
|
|
|
|
if [ ${ret_rsync} -eq 0 ]; then |
|
|
|
|
if [ "${LOG_TO_FILE}" = 'true' ]; then |
|
|
|
|
printf "%s\n" "[$(date '+%Y-%m-%d, %T') OK backup_mobile_phone] "${ALIAS}" ; \ |
|
|
|
|
$((${FINISH}-${START}))s" >> "${LOG_FILE}" |
|
|
|
|
fi |
|
|
|
|
if [ "${LOG_TO_EMAIL}" = 'true' ]; then |
|
|
|
|
printf "%s\n" "Backup on "${ALIAS}" took $((${FINISH}-${START}))s" \ |
|
|
|
|
| mail -r "${EMAIL_SENDER}" -s 'Backup complete' "${EMAIL_RECIPIENT}" |
|
|
|
|
fi |
|
|
|
|
else |
|
|
|
|
echo "OK "${AKA}" |
|
|
|
|
if [ "${LOG_TO_FILE}" = 'true' ]; then |
|
|
|
|
printf "%s\n" "[$(date '+%Y-%m-%d, %T') FAILED backup_mobile_phone \ |
|
|
|
|
ret_rsync=${ret_rsync}] "${DST}"" \ |
|
|
|
|
>> /var/log/rsync.log |
|
|
|
|
fi |
|
|
|
|
if [ "${LOG_TO_EMAIL}" = 'true' ]; then |
|
|
|
|
printf "%s\n" "Backup error on "${ALIAS}". Error code ${ret_rsync}" \ |
|
|
|
|
| mail -r "${EMAIL_SENDER}" -s 'Backup error' "${EMAIL_RECIPIENT}" |
|
|
|
|
fi |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
# Unmount after finishing. |
|
|
|
|
fusermount3 -u "${MOUNT_DIR}" |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Finally run it. If it works you can add it to crontab for automatic backups. |
|
|
|
|
To run the script you simply need to pass the alias as argument: |
|
|
|
|
- Edit the following configuration file: |
|
|
|
|
|
|
|
|
|
```shell |
|
|
|
|
$ <path_to_script> <alias> |
|
|
|
|
USERNAME='username0' |
|
|
|
|
PASSWORD='password0' |
|
|
|
|
ADDRESS='1.2.3.4' |
|
|
|
|
PORT='65432' |
|
|
|
|
MOUNT_DIR='/home/user/mountpoints/user0' |
|
|
|
|
DST_DIR='/home/user/backup/user0' |
|
|
|
|
|
|
|
|
|
# Friendlier name. |
|
|
|
|
ALIAS='user 0' |
|
|
|
|
|
|
|
|
|
LOG_TO_EMAIL='true' |
|
|
|
|
EMAIL_SENDER='Computer <your.email@address.com>' |
|
|
|
|
# You can use aliases if your mailing system is set up correctly. |
|
|
|
|
EMAIL_RECIPIENT='all' |
|
|
|
|
|
|
|
|
|
LOG_TO_FILE='true' |
|
|
|
|
LOG_FILE='/var/log/rsync.log' |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
with `<alias>` being the value of the `ALIAS` variable in the script. |
|
|
|
|
- Finally run it. If it works you can add it to crontab for automatic backups. |
|
|
|
|
To run the script you simply need to pass the configuration file as argument: |
|
|
|
|
|
|
|
|
|
```shell |
|
|
|
|
$ ${PATH_TO_SCRIPT} ${PATH_TO_CONFIGURATION_FILE} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
# Problems and explanation |
|
|
|
|
|
|
|
|
@ -138,12 +158,6 @@ filesystem` worked best, although the location that will be synced will
|
|
|
|
|
usually be `/storage/emulated/0` and cannot be changed to use, for example, |
|
|
|
|
the external SD card. |
|
|
|
|
|
|
|
|
|
## Partial file transfers |
|
|
|
|
|
|
|
|
|
As you can see from the script's code, the option ``--checksum`` is useful |
|
|
|
|
in case of partial file transfers, especially with flaky connections such |
|
|
|
|
as the ones we find in mobile devices. |
|
|
|
|
|
|
|
|
|
# Alternatives |
|
|
|
|
|
|
|
|
|
There aren't many *free software* alternatives that work like this for Android. |
|
|
|
|