1 votos

El comando de dormir largo no funciona en script

He escrito un su.d script para realizar periódicamente (cada 4 horas) una copia de seguridad de los datos de una app utilizando un bucle sleep comando:

#!/system/bin/sh

(
  # Wait for boot to complete
  until [ "$(getprop sys.boot_completed)" ]
  do
    sleep 300
  done

  while true
  do
    (
      new_dir="/storage/emulated/0/temp/AppData/$(date '+%Y%m%d-%H%M')"
      mkdir -p $new_dir
      cp /data/data/com.example.app/files/*.json $new_dir

      echo "$(date '+%F %T') | app data backup OK!" >> /storage/emulated/0/su.d.log
    ) &

    sleep 14400 # 4 hours
  done
) &

En la práctica, el script hace una copia de seguridad de los datos sólo después del arranque, no cada 4 horas.

Sin embargo, si entro en un shell remoto a través de adb y dejarlo solo, entonces los datos sí se respaldan cada 4 horas.

¿Cómo puedo forzar la copia de seguridad periódica sin estar permanentemente conectado a un PC? (¿Y por qué no funciona como se espera?)


EDITS

  1. El comentario de @Irfan Latif me dio la idea de probar un intérprete diferente (busybox ash - #!/system/xbin/sh ), pero el resultado fue el mismo. Probaré la sugerencia de @mirabilos de daemonizar ( sh -T- -c '...' ) siguiente.

  2. Probado la sugerencia de @mirabilos de daemonise con el mismo resultado: respalda los datos sólo después del arranque.

  3. Probado nohup :

    nohup /system/bin/sh -T- -c '...' >/dev/null 2>&1 &

    El mismo resultado.

2 votos

No recuerdo exactamente pero ya lo había resuelto una vez. Creo que el problema era con /system/bin/sh (korn shell). Se comporta de forma inesperada cuando no está conectado a un terminal y bifurca un shell en segundo plano. Para la línea de comandos, puedes optar por busybox cron para programar las tareas. Para la interfaz de usuario, utiliza una aplicación como Tasker.

1 votos

Puedes optar por el demonio cron simplemente creando un crontabs archivo. Esto parece una solución más apropiada para las tareas repetidas en lugar de utilizar shell en el fondo. Todo lo que necesitas para ejecutar en el arranque es: busybox crond -c /path/to/crontabs . Si quieres seguir con lo de la cáscara, usa set -x y exec &> para tomar registros de su.d script con marcas de tiempo para encontrar cuándo y por qué falla la ejecución del shell.

0 votos

Hombre Se pueden utilizar alternativas, ver aquí: < unix.stackexchange.com/questions/482725/ >

3voto

mirabilos Puntos 165

Si es lo del terminal que escribió @IrfanLatif, prueba esto:

#!/system/bin/sh
# run a command block in the background, detached from all terminals
/system/bin/sh -T- -c '
    # Wait for boot to complete
    until [ "$(getprop sys.boot_completed)" ]; do
        sleep 300
    done

    while true; do
        (
            new_dir="/storage/emulated/0/temp/AppData/$(date '\''+%Y%m%d-%H%M'\'')"
            mkdir -p "$new_dir"
            cp /data/data/com.example.app/files/*.json "$new_dir"

            echo "$(date '\''+%F %T'\'') | app data backup OK!" >>/storage/emulated/0/su.d.log
        ) &

        sleep 14400 # 4 hours
    done
'

El -T- le dice al shell que daemon() ise, es decir, sustituir stdin, stdout, stderr por /dev/null y el comando en el fondo. Tal vez esto ayude.

No tengo ni idea de por qué esto no funcionaría de otra manera. Revelación completa: soy el mksh desarrollador.

1voto

andronoid Puntos 6

Al no tener éxito con sleep Terminé yendo a la crond como sugiere @Irfan Latif:

  • /system/su.d/99crond (-rwx------ root root)

    #!/system/bin/sh
    
    # File: 99crond
    # Desc: Start cron daemon
    
    (
      # Wait for boot to complete
      until [ "$(getprop sys.boot_completed)" ]
      do
        sleep 2
      done
    
      # Symlink default cron dir to /data/local/crontabs
      mount -o remount,rw /
      mkdir -p /var/spool/cron
      ln -s /data/local/crontabs /var/spool/cron/crontabs
      mount -o remount,ro /
    
      crond -b
    
      echo "$(date '+%F %T') | su.d/99crond OK!" >> /storage/emulated/0/su.d.log
    ) &
  • /data/local/crontabs/root (-rw------- root root)

    # /data/local/crontabs/root: Android root user crontab
    
    SHELL=/system/bin/sh
    PATH=/sbin:/system/bin:/system/xbin:/data/local/bin
    
    #.--------------------------- Minute (M) (0--59)
    #|    .---------------------- Hour (H) (0--23, 0 = midnight)
    #|    |     .---------------- Day of Month (DoM) (1--31)
    #|    |     |     .---------- Month (MON) (1--12) OR jan,feb,mar, ...
    #|    |     |     |     .---- Day of Week (DoW) (0--6, Sunday = 0 or 7) OR sun,mon,tue, ...
    #|    |     |     |     |
    #M    H     DoM   MON   DoW   COMMAND
    0     */4   *     *     *     /data/local/bin/cron_backup.sh
    #

    MÁS LECTURAS

  • /data/local/bin/cron_backup.sh (-rwxr-xr-x root shell)

    #!/system/bin/sh
    
    # File: cron_backup.sh
    # Desc: Back up app data (periodically with crond)
    
    new_dir="/storage/emulated/0/temp/AppData/$(date '+%Y%m%d-%H%M')"
    mkdir -p "$new_dir"
    cp /data/data/com.example.app/files/*.json "$new_dir"
    
    echo "$(date '+%F %T') | cron_backup.sh OK!" >> /storage/emulated/0/crond.log

Como señala @Ramast aquí Estos tres archivos por sí solos no fueron suficientes para conseguir crond trabajando: /system/etc/passwd también es necesario para el usuario root para ser reconocido, así que...

mount -o remount,rw /system
echo "root:x:0:0:root:/data:/system/bin/sh" >> /system/etc/passwd
chmod 644 /system/etc/passwd
mount -o remount,ro /system

Una vez hecho todo esto, los datos se respaldan periódicamente según se desee.

1voto

Dima Puntos 11

Mi comentario no funciona también. Lo he entendido, sleep no funciona, entonces la pantalla está apagada.

Quizás debas mantener el sistema despierto para sleep para que funcione.

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X