Trabajar con cron para Android y agregar un script de shell para la ejecución automática cuando se inicia el dispositivo



Debido al hecho de que los dispositivos móviles han tenido una amplia funcionalidad, las tareas de automatización pueden transferirse fácilmente a ellos. Y, lo mejor posible, cron es igual de bueno para ejecutarlos. Pero si cron toma un poco de tiempo en sistemas Linux "ordinarios", entonces un dispositivo Android requiere un trabajo más complicado para configurarlo.

Si está interesado en el tema de la automatización y desea que sus scripts de shell se inicien inmediatamente después de que se inicie el dispositivo, e incluso podría iniciarse con un temporizador, ¡bienvenido al gato!

Prólogo


Me dedico a la automatización de dispositivos móviles para Android. Y durante la ejecución de scripts automáticos, se producen muchas situaciones imprevistas, incluso si se utilizan los mismos dispositivos para las pruebas.

Problemas más populares:

0. El script de automatización no hace lo que querías.
1. La aplicación móvil se descarga automáticamente
2. Reinicio automático del teléfono
3. La aplicación móvil no se inicia automáticamente después de reiniciar
4. El módulo Wi-Fi se apaga aleatoriamente, no encuentra la red, no se conecta a la red
5. La red móvil desapareció repentinamente
6. El teléfono entró en modo de suspensión
7. El proxy se cayó o el servidor mismo o el servidor devolvió una respuesta extraña

Debido a esto, debe monitorear constantemente el dispositivo y detectar estas situaciones imprevistas.



Por lo tanto, llegué a la conclusión de que cron con los scripts "correctos" le permitirá rastrear fallas de software y restaurar el script de automatización o ejecutarlo nuevamente. Pero resultó que, aunque Android contiene el kernel de Linux, hay algunos matices especiales con los que tuve que lidiar. ¡Así que comencemos con la configuración!

Configuración de Cron


Personaliza el entorno


  1. Instale adb para acceder al dispositivo a través del shell utilizando un cable usb.
  2. Abrimos la sección Para desarrolladores . Para hacer esto, vaya a la sección Acerca del teléfono y haga algunos clics en el número de compilación o algo similar.
  3. Vamos a la sección Para desarrolladores y lo activamos. Conectamos el dispositivo a la computadora y permitimos el acceso en esta computadora a este dispositivo.
  4. Agregue root para su dispositivo. Las opciones más comunes son SuperSu , Magisk y Kingroot . Vaya a w3bsit3-dns.com y encuentre la opción raíz para su dispositivo. Lamentablemente, no hay una raíz universal.
  5. Instalamos BusyBox (también está en w3bsit3-dns.com, por ejemplo), ya que solo contiene un programa cron.

Ajuste de inicio manual


  1. Nos conectamos al teléfono usando adb shell (si adb no está registrado en su variable de entorno, luego agregue la ruta completa.
  2. Vaya al modo raíz con el comando su
  3. Verificamos la presencia del programa cron y vemos la configuración usando el comando crond -h

resultado de ejecución
crond: invalid option -- h BusyBox v1.29.2-Stericson (2018-08-12 11:19:12 EDT) multi-call binary. Usage: crond -fbS -l N -d N -L LOGFILE -c DIR -f Foreground -b Background (default) -S Log to syslog (default) -l N Set log level. Most verbose 0, default 8 -d N Set log level, log to stderr -L FILE Log to FILE -c DIR Cron dir. Default:/var/spool/cron/crontabs 


Como puede ver en la última línea, las instrucciones predeterminadas deben almacenarse en el directorio / var / spool / cron / crontabs , que no se crea automáticamente y si ejecutamos el comando
 crond -b 
y luego verifique si el proceso comenzó a través de
 ps | grep crond 
, entonces puede que no esté allí, porque no pudo obtener ninguna instrucción. Entonces ejecutemos el comando
 crond -b -fd0 
y ver cuál es el motivo. Lo más probable es que tenga un error similar:
crond: can't change directory to '/var/spool/cron/crontabs': No such file or directory . En este caso, esto es normal, porque en el futuro, nosotros mismos indicaremos la ruta al archivo ejecutable crontab.

4. Cree un archivo crontab simple:

 mkdir /data/crontab echo "*/1 * * * * echo 'text' >> /sdcard/test.txt" > /data/crontab/root 

Ahora tenemos una tarea que cada minuto agregará la palabra texto al archivo /sdcard/test.txt
Lanzamos:
 crond -b -fd0 -c /data/crontab 
y obtenga el siguiente registro:

 crond: crond (busybox 1.29.2-Stericson) started, log level 0 crond: ignoring file 'root' (no such user) ... 

Por supuesto, es un poco sorprendente, porque si ejecutamos el comando whoami, como resultado, devolverá root .

5. Agregue el usuario root, ya que crond pregunta:

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

Debido a la falta de este archivo, me di cuenta de que en el sistema Android no está involucrado en absoluto. Si está seguro de dónde almacenará sus archivos crontab, puede reemplazar la línea / system / etc / crontabs con la que necesita. Ejecute el comando nuevamente

 crond -b -fd0 -c /data/crontab 

Y obtenemos lo siguiente:

 crond: user:root entry:*/1 * * * * echo 'text' >> /sdcard/test.txt 111111111111111111111111111111111111111111111111111111111111 111111111111111111111111 11111111111111111111111111111111 111111111111 1111111 crond: wakeup dt=16 crond: file root: crond: line echo 'text' >> /sdcard/test.txt crond: job: 0 echo 'text' >> /sdcard/test.txt crond: can't change directory to '/system/etc/crontabs' crond: can't change directory to '/var/spool/cron': No such file or directory crond: USER root pid 12849 cmd echo 'text' >> /sdcard/test.txt 

Aunque, según el registro, la tarea se registró en crond, pero en mi caso el archivo no se creó. El problema se puede resolver de manera muy simple:

 mkdir -p /system/etc/crontabs 

Bueno, él quiere que exista un directorio allí, ¿quiénes somos para prohibirlo? Comenzamos de nuevo y vemos:

 crond: user:root entry:*/1 * * * * echo 'text' >> /sdcard/test.txt 111111111111111111111111111111111111111111111111111111111111 111111111111111111111111 11111111111111111111111111111111 111111111111 1111111 crond: wakeup dt=12 crond: file root: crond: line echo 'text' >> /sdcard/test.txt crond: job: 0 echo 'text' >> /sdcard/test.txt crond: child running /system/bin/sh crond: USER root pid 13033 cmd echo 'text' >> /sdcard/test.txt 

Los errores desaparecieron y apareció la línea crond: child running / system / bin / sh . Finalmente, cron se ha terminado con éxito, ¡y puedes pasar a la segunda parte!

Descarga automática de script de shell


El sistema Linux tiene un directorio init.d que es responsable del inicio automático inmediatamente después del arranque del sistema, ¡así que intentemos de esta manera!

1. Compruebe si este directorio existe en su dispositivo (esto es /etc/init.d o /system/etc/init.d : esta es la misma partición montada, etc.). En mi caso, no lo es. Bueno, entonces crea:

 mount -o remount,rw /system mkdir /system/etc/init.d chmod 0755 /system/etc/init.d mount -o remount,ro /system 

Ahora agregue un script simple allí, por ejemplo:

 echo "echo 'Init.d is working !!!' >> /sdcard/init_test.log" > /system/etc/init.d/90my_script chmod 777 /system/etc/init.d/90my_script 

Reiniciamos el dispositivo y vemos si ocurrió un milagro ... Desafortunadamente, mi archivo no apareció.

Examinamos el sistema más a fondo y buscamos algún archivo de inicio que pueda ejecutar scripts después del lanzamiento. Tenía un archivo en /init.rc en mi dispositivo. Bueno, intentemos cambiarlo y reiniciar el dispositivo:

 mount -o remount,rw / echo "echo 'Init.d is working !!!' >> /sdcard/init_test.log" >> /init.rc mount -o remount,ro / reboot 

Pero el archivo no fue creado nuevamente. Vamos a ver el archivo /init.rc y nuestro registro desapareció y el archivo no pareció cambiar, porque la fecha de creación es bastante extraña (en mi caso, 1 de enero de 70 05:00:00).

Seguimos entendiendo, y resulta que este archivo está almacenado en boot.img , y cada vez que sale de él. Y para cambiar la funcionalidad del archivo init.rc , debe hacer todo esto .

Pero hay una manera más fácil de ayudar a resolver este problema. Para este método, podemos usar el siguiente script de shell (gracias a Ryuinferno):

Script de Shell
 #!/system/bin/sh #Script to enable init.d by Ryuinferno @ XDA error_msg(){ echo "You do not need this mod..." sleep 1 echo "If you are reapplying, please delete these files if present:" echo "/system/bin/sysinit" sleep 1 echo "/system/etc/install-recovery.sh" sleep 1 echo "/system/etc/install-recovery-2.sh" sleep 1 echo "And run again..." sleep 1 echo "If init.d is still not working, read the FAQ part in my thread..." sleep 1 echo "Aborting..." mount -o remount,ro -t auto /system echo "" echo "Ryuinferno @ XDA" exit 1 } echo "Init.d Enabler by Ryuinferno @ XDA" echo "" sleep 1 id=`id`; id=`echo ${id#*=}`; id=`echo ${id%%\(*}`; id=`echo ${id%% *}` if [ "$id" != "0" ] && [ "$id" != "root" ]; then echo "Script NOT running as root!" sleep 1 echo "Superuser access not granted!" sleep 1 echo "Please type 'su' first before running this script..." exit 1 else echo "Hello Supaa User! :P" echo "" sleep 1 fi if [ ! "'which busybox'" ]; then echo "busybox NOT INSTALLED!" sleep 1 echo "Please install busybox first!" exit 1 else echo "busybox found!" sleep 1 fi bbb=0 if [ ! "`which grep`" ]; then bbb=1 echo "grep applet NOT FOUND!" sleep 1 else echo "Awesome! grep found! :D" sleep 1 fi if [ ! "`which run-parts`" ]; then bbb=1 echo "run-parts applet NOT FOUND!" sleep 1 else echo "Good! run-parts found! :)" echo "" sleep 1 fi if [ $bbb -eq 1 ] ; then echo "" echo "Required applets are NOT FOUND!" echo "" sleep 1 echo "Please reinstall busybox!" exit 1 fi echo "Great! Let's proceed..." echo "" sleep 1 echo "Press enter to continue..." read enterKey clear sleep 1 echo "Mounting system as rewritable..." mount -o remount,rw -t auto /system sleep 1 echo "Removing old sysinit file" rm /system/bin/sysinit sleep 1 echo "" echo "Checking for the presence of sysinit in /system/bin..." sleep 1 if [ -e /system/bin/sysinit ]; then echo "sysinit found..." if [ -z "`cat /system/bin/sysinit | grep "init.d"`" ]; then echo "Adding lines to sysinit..." echo "" >> /system/bin/sysinit echo "# init.d support" >> /system/bin/sysinit echo "" >> /system/bin/sysinit echo "export PATH=/sbin:/system/sbin:/system/bin:/system/xbin" >> /system/bin/sysinit echo "run-parts /system/etc/init.d" >> /system/bin/sysinit echo "" >> /system/bin/sysinit else echo "" echo "Your sysinit should already be running the scripts in init.d folder at boot..." error_msg fi else echo "sysinit not found, creating file..." echo "#!/system/bin/sh" > /system/bin/sysinit echo "# init.d support" >> /system/bin/sysinit echo "" >> /system/bin/sysinit echo "export PATH=/sbin:/system/sbin:/system/bin:/system/xbin" >> /system/bin/sysinit echo "run-parts /system/etc/init.d" >> /system/bin/sysinit echo "" >> /system/bin/sysinit fi sleep 1 echo "Setting correct permissions and ownership for sysinit..." chmod 755 /system/bin/sysinit chown 0.2000 /system/bin/sysinit sleep 1 echo "" echo "Checking for the presence of install-recovery.sh..." sleep 1 if [ -f /system/etc/install-recovery.sh ] && [ -z "`cat /system/etc/install-recovery.sh | grep "daemon"`" ]; then if [ ! -z "`cat /system/etc/install-recovery.sh | grep "init.d"`" ];then echo "Your install-recovery.sh seems to be already modified for init.d..." error_msg fi echo "install-recovery.sh found, renaming it as install-recovery-2.sh..." mv /system/etc/install-recovery.sh /system/etc/install-recovery-2.sh echo "Recreating install-recovery.sh..." echo "#!/system/bin/sh" > /system/etc/install-recovery.sh echo "# init.d support" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh echo "/system/bin/sysinit" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh echo "# excecuting extra commands" >> /system/etc/install-recovery.sh echo "/system/etc/install-recovery-2.sh" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh elif [ -f /system/etc/install-recovery.sh ] && [ ! -z "`cat /system/etc/install-recovery.sh | grep "daemon"`" ]; then if [ -f /system/etc/install-recovery-2.sh ] && [ ! -z "`cat /system/etc/install-recovery-2.sh | grep "init.d"`" ];then echo "Your install-recovery-2.sh seems to be already modified for init.d..." error_msg fi echo "install-recovery.sh is used for superuser, using install-recovery-2.sh instead..." if [ -f /system/etc/install-recovery-2.sh ]; then echo "" >> /system/etc/install-recovery-2.sh echo "# init.d support" >> /system/etc/install-recovery-2.sh echo "/system/bin/sysinit" >> /system/etc/install-recovery-2.sh echo "" >> /system/etc/install-recovery-2.sh else echo "#!/system/bin/sh" > /system/etc/install-recovery-2.sh echo "# init.d support" >> /system/etc/install-recovery-2.sh echo "" >> /system/etc/install-recovery-2.sh echo "/system/bin/sysinit" >> /system/etc/install-recovery-2.sh echo "" >> /system/etc/install-recovery-2.sh fi if [ -z "`cat /system/etc/install-recovery.sh | grep "install-recovery-2.sh"`" ]; then echo "" >> /system/etc/install-recovery.sh echo "# extra commands" >> /system/etc/install-recovery.sh echo "/system/etc/install-recovery-2.sh" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh fi else echo "install-recovery.sh not found, creating it..." echo "#!/system/bin/sh" > /system/etc/install-recovery.sh echo "# init.d support" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh echo "/system/bin/sysinit" >> /system/etc/install-recovery.sh echo "" >> /system/etc/install-recovery.sh fi sleep 1 echo "Setting the correct permissions and ownership for install-recovery.sh..." echo "Also for install-recovery-2.sh if it exists..." chmod 755 /system/etc/install-recovery.sh chown 0.0 /system/etc/install-recovery.sh if [ -f /system/etc/install-recovery-2.sh ]; then chmod 755 /system/etc/install-recovery-2.sh chown 0.0 /system/etc/install-recovery-2.sh fi sleep 1 echo "" echo "Checking for the presence of the init.d folder..." sleep 1 if [ -d /system/etc/init.d ]; then echo "init.d folder found..." else echo "init.d folder not found, creating the folder..." mkdir /system/etc/init.d fi sleep 1 echo "" echo "Creating basic init.d scripts..." echo "#!/system/bin/sh" > /system/etc/init.d/08setperm echo "#set correct permissions to /system/etc/init.d folder" >> /system/etc/init.d/08setperm echo "" >> /system/etc/init.d/08setperm echo "mount -o remount,rw -t auto /system" >> /system/etc/init.d/08setperm echo "chmod -R 777 /system/etc/init.d" >> /system/etc/init.d/08setperm echo "mount -o remount,ro -t auto /system" >> /system/etc/init.d/08setperm echo "" >> /system/etc/init.d/08setperm echo "#!/system/bin/sh" > /system/etc/init.d/00test echo "#init.d test" >> /system/etc/init.d/00test echo "" >> /system/etc/init.d/00test echo "if [ -f /data/Test.log ]; then" >> /system/etc/init.d/00test echo "rm /data/Test.log" >> /system/etc/init.d/00test echo "fi" >> /system/etc/init.d/00test echo "" >> /system/etc/init.d/00test echo 'echo "Init.d is working !!!" >> /data/Test.log' >> /system/etc/init.d/00test echo 'echo "excecuted on $(date +"%d-%m-%Y %r" )" >> /data/Test.log' >> /system/etc/init.d/00test echo "" >> /system/etc/init.d/00test sleep 1 echo "Creating permissive SELinux script..." sleep 1 echo "#!/system/bin/sh" >> /system/etc/init.d/01permissive echo "#Init.d Permissive SELinux" >> /system/etc/init.d/01permissive echo "" >> /system/etc/init.d/01permissive echo "busybox mount -o remount,rw -t auto /system" >> /system/etc/init.d/01permissive echo "" >> /system/etc/init.d/01permissive echo "setenforce 0" >> /system/etc/init.d/01permissive echo "SELINUX=permissive" >> /system/etc/init.d/01permissive echo "" >> /system/etc/init.d/01permissive sleep 1 echo "Setting correct permissions and ownership for init.d folder and scipts..." chmod 777 /system/etc/init.d chmod 777 /system/etc/init.d/08setperm chmod 777 /system/etc/init.d/00test chmod 777 /system/etc/init.d/01permissive chown 0.0 /system/etc/init.d chown 0.0 /system/etc/init.d/08setperm chown 0.0 /system/etc/init.d/00test chown 0.0 /system/etc/init.d/01permissive sleep 1 echo "" echo "Mounting system as read-only..." mount -o remount,ro -t auto /system sleep 1 echo "" echo "Done!!!" sleep 1 echo "Please reboot at least twice before checking /data..." sleep 1 echo "If init.d is working, you will see a Test.log in /data..." sleep 1 echo "" echo "Enjoy!!! =)" echo "Ryuinferno @ XDA 2013" exit 


Comenzando con el guión! En mi caso, se llamará init.sh.
1. Descargue el archivo en la tarjeta sd del dispositivo móvil:
 adb push /tmp/init.sh /sdcard 

2. Copie a la memoria del dispositivo móvil y configure los derechos necesarios:
 adb shell su cp /sdcard/init.sh /data/init.sh chmod 777 /data/init.sh 

3. Ejecutar para ejecución:
 /data/init.sh 

Y preste atención al registro que se muestra. Aquí está mi registro:
Ejecutar registro
 Init.d Enabler by Ryuinferno @ XDA Hello Supaa User! :P busybox found! Awesome! grep found! :D Good! run-parts found! :) Great! Let's proceed... Press enter to continue... Mounting system as rewritable... Removing old sysinit file rm: /system/bin/sysinit: No such file or directory Checking for the presence of sysinit in /system/bin... sysinit not found, creating file... Setting correct permissions and ownership for sysinit... Checking for the presence of install-recovery.sh... install-recovery.sh not found, creating it... Setting the correct permissions and ownership for install-recovery.sh... Also for install-recovery-2.sh if it exists... Checking for the presence of the init.d folder... init.d folder found... Creating basic init.d scripts... Creating permissive SELinux script... Setting correct permissions and ownership for init.d folder and scipts... Mounting system as read-only... Done!!! Please reboot at least twice before checking /data... If init.d is working, you will see a Test.log in /data... Enjoy!!! =) Ryuinferno @ XDA 2013 


Como puede ver en el registro, no hay errores, ¡así que no dude en reiniciar el dispositivo! Tal vez alguien ya trabajó y podría encontrar el archivo /data/Test.log , pero no lo tengo. Verifique el directorio /system/etc/init.d con el comando ls :

 00test 01permissive 08setperm 

Como puede ver, las tareas se han creado con éxito. Es posible que aún tenga que cambiar boot.img , pero veamos al principio dónde está el archivo install-recovery.sh con el comando

 find / -name "install-recovery.sh" ... /system/bin/install-recovery.sh /system/etc/install-recovery.sh ... 

Como podemos ver, tenemos 2 archivos que se encuentran en diferentes lugares. En la fecha de creación, podemos notar que el script creó el archivo en el directorio /system/etc/install-recovery.sh , aunque, tal vez, en algunos casos debería crearlo en / system / etc. Cambiemos el nombre del archivo a bin y copiemos el archivo, etc.

 mount -o remount,rw /system mv /install-recovery.sh /system/bin/install-recovery2.sh cp /install-recovery.sh /system/bin/ 


UPD : tenga en cuenta que el contexto de seguridad para ambos archivos debe coincidir. Y si de repente se perdió durante la copia (aunque en teoría esto no debería ser así), deberá restaurarlo (por ejemplo, a través de la utilidad chcon ). Vea la información completa del archivo con ls -lZ :
 ls -lZ /system/etc/install-recovery.sh # -rwxr-xr-x root root u:object_r:system_file:s0 install-recovery.sh 

Aquí u: object_r: system_file: s0 es contextos de seguridad.

Y nuevamente reiniciamos el dispositivo ... ¡Y ahora, finalmente, el ÉXITO tan esperado! ¡Ha aparecido el archivo /data/Test.log !

Una vez que todo funcione, vaya a /system/etc/init.d y cree un script de shell. Y en él, simplemente ejecuta nuestro crond para ejecutar:

 echo "#!/system/bin/sh crond -b -L /sdcard/error.log -c /data/crontab" > /system/etc/init.d/99cronstart chmod 777 /system/etc/init.d/99cronstart reboot 

Después de la descarga, verifique si crond ha comenzado:

 ps | grep crond root 414 1 9532 236 hrtimer_na 000dcf90 S crond 

Y podríamos terminar ahora, pero esperemos un minuto y veamos si había un registro en nuestro archivo ... Bueno, como ya entendieron, nuevamente, nada funcionó. El hecho es que este proceso debe ejecutarse desde un superusuario. Cambie el script en el archivo 99cronstart :

 echo "#!/system/bin/sh /su/bin/su -c crond -b -L /sdcard/error.log -c /data/crontab" > /system/etc/init.d/99cronstart reboot 


UPD : Quizás en su caso su tenga una ruta diferente, luego use el comando que su y reemplace la ruta con la suya.

¡Ahora nuestro dispositivo Android admite tareas cron y puede contener scripts de shell para el inicio automático!

Y finalmente, el script que ejecutará nuestra aplicación, si no está en los procesos y guardará información sobre lo que estaba en la pantalla principal antes de iniciar nuestra aplicación:

 proc=$(ps | grep "com.test.app") if [ "$proc" == "" ]; then dumpsys window | grep CurrentFocus > /sdcard/current_focus.dump sleep 1 am start -n com.test.app/com.test.app.activities.MainActivity fi 

Source: https://habr.com/ru/post/468337/


All Articles