Utilisation de cron pour Android et ajout d'un script shell pour l'exécution automatique au démarrage de l'appareil



Du fait que les appareils mobiles disposent depuis longtemps de fonctionnalitĂ©s Ă©tendues, les tĂąches d'automatisation peuvent y ĂȘtre facilement transfĂ©rĂ©es. Et, aussi bien que possible, cron est tout aussi bon pour les exĂ©cuter. Mais si cron prend un peu de temps dans les systĂšmes Linux "ordinaires", un appareil Android nĂ©cessite un travail plus compliquĂ© pour le configurer.

Si vous ĂȘtes intĂ©ressĂ© par le sujet de l'automatisation et que vous souhaitez que vos scripts shell s'exĂ©cutent immĂ©diatement aprĂšs le dĂ©marrage de l'appareil, et pourraient mĂȘme dĂ©marrer sur une minuterie - bienvenue au chat!

Préface


Je suis engagĂ© dans l'automatisation des appareils mobiles pour Android. Et lors de l'exĂ©cution de scripts automatiques, de nombreuses situations imprĂ©vues se produisent, mĂȘme si les mĂȘmes appareils sont utilisĂ©s pour les tests.

ProblĂšmes les plus courants:

0. Le script d'automatisation ne fait pas ce que vous vouliez.
1. L'application mobile est téléchargée automatiquement
2. Redémarrage automatique du téléphone
3. L'application mobile ne démarre pas automatiquement aprÚs un redémarrage
4. Le module Wi-Fi s'éteint de maniÚre aléatoire, ne trouve pas le réseau, ne se connecte pas au réseau
5. Le réseau mobile a soudainement disparu
6. Le téléphone est passé en mode veille
7. Le proxy a chutĂ© ou le serveur lui-mĂȘme ou le serveur a renvoyĂ© une rĂ©ponse Ă©trange

Pour cette raison, vous devez constamment surveiller l'appareil et détecter ces situations imprévues.



Ainsi, je suis arrivé à la conclusion que cron avec les scripts "corrects" vous permettra de suivre les pannes logicielles et de restaurer le script d'automatisation ou de le relancer. Mais il s'est avéré que, bien qu'Android contienne le noyau Linux, il y a des nuances spéciales avec lesquelles j'ai dû faire face. Commençons donc la configuration!

Configuration de Cron


Personnalisez l'environnement


  1. Installez adb pour accéder à l'appareil via le shell à l'aide d'un cùble USB.
  2. Nous ouvrons la section Pour les dĂ©veloppeurs . Pour ce faire, allez dans la section À propos du tĂ©lĂ©phone et faites quelques clics sur le numĂ©ro de build ou quelque chose de similaire.
  3. Nous allons à la section Pour les développeurs et l'activons. Nous connectons l'appareil à l'ordinateur et autorisons l'accÚs sur cet ordinateur à cet appareil.
  4. Ajoutez la racine pour votre appareil. Les options les plus courantes sont SuperSu , Magisk et Kingroot . Accédez à w3bsit3-dns.com et recherchez l'option racine pour votre appareil. Malheureusement, il n'y a pas de racine universelle.
  5. Nous installons BusyBox (c'est aussi sur w3bsit3-dns.com, par exemple), car il contient juste un programme cron.

Réglage de démarrage manuel


  1. Nous nous connectons au téléphone à l'aide du shell adb (si adb n'est pas enregistré dans votre variable d'environnement, ajoutez le chemin complet.
  2. Passez en mode root avec la commande su
  3. Nous vérifions la présence du programme cron et voyons les paramÚtres à l'aide de la commande crond -h

résultat d'exécution
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 


Comme vous pouvez le voir sur la derniĂšre ligne, les instructions par dĂ©faut doivent ĂȘtre stockĂ©es dans le rĂ©pertoire / var / spool / cron / crontabs , qui n'est pas crĂ©Ă© automatiquement et si nous exĂ©cutons la commande
 crond -b 
puis vérifiez si le processus a commencé
 ps | grep crond 
, alors il peut ne pas ĂȘtre lĂ , car il n'a pu obtenir aucune instruction. ExĂ©cutons donc la commande
 crond -b -fd0 
et voyez quelle est la raison. Vous aurez probablement une erreur similaire:
crond: can't change directory to '/var/spool/cron/crontabs': No such file or directory . Dans ce cas, c'est normal, car Ă  l'avenir, nous indiquerons nous-mĂȘmes le chemin vers le fichier exĂ©cutable crontab.

4. Créez un fichier crontab simple:

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

Nous avons maintenant une tĂąche qui, chaque minute, ajoutera le mot texte au fichier /sdcard/test.txt
Nous lançons:
 crond -b -fd0 -c /data/crontab 
et obtenez le journal suivant:

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

Bien sûr, c'est un peu surprenant, car si nous exécutons la commande whoami, elle retournera root en conséquence.

5. Ajoutez l'utilisateur root, car crond demande:

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

En raison de l'absence de ce fichier, j'ai rĂ©alisĂ© que dans le systĂšme Android, il n'Ă©tait pas du tout impliquĂ©. Si vous ĂȘtes sĂ»r de l'emplacement de stockage de vos fichiers crontab, vous pouvez remplacer la ligne / system / etc / crontabs par celle dont vous avez besoin. ExĂ©cutez Ă  nouveau la commande

 crond -b -fd0 -c /data/crontab 

Et nous obtenons ce qui suit:

 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 

Bien que, selon le journal, la tĂąche ait Ă©tĂ© enregistrĂ©e dans crond, mais dans mon cas, le fichier n'a pas Ă©tĂ© crĂ©Ă©. Le problĂšme peut ĂȘtre rĂ©solu trĂšs simplement:

 mkdir -p /system/etc/crontabs 

Eh bien, il veut qu'un répertoire existe là-bas, qui sommes-nous pour lui interdire! Nous recommençons et voyons:

 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 

Les erreurs ont disparu et la ligne crond: enfant exécutant / system / bin / sh est apparue . Enfin, cron a été clÎturé avec succÚs, et vous pouvez passer à la deuxiÚme partie!

Téléchargement automatique du script shell


Le systÚme Linux a un répertoire init.d qui est responsable du démarrage automatique immédiatement aprÚs le démarrage du systÚme, alors essayons de cette façon!

1. VĂ©rifiez si ce rĂ©pertoire existe sur votre appareil (c'est /etc/init.d ou /system/etc/init.d - c'est la mĂȘme partition montĂ©e, etc.). Dans mon cas, ce n'est pas le cas. Eh bien, alors crĂ©ez:

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

Maintenant, ajoutez-y un script simple, par exemple:

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

Nous redémarrons l'appareil et voyons si un miracle s'est produit ... Malheureusement, mon fichier n'est pas apparu.

Nous examinons le systÚme plus loin et recherchons un fichier init qui peut exécuter des scripts aprÚs le lancement. J'avais un fichier dans /init.rc sur mon appareil. Eh bien, essayons de le changer et de redémarrer l'appareil:

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

Mais le fichier n'a pas été recréé. Nous allons regarder le fichier /init.rc et notre dossier a disparu et le fichier ne semble pas changer, car la date de création est assez étrange (dans mon cas, 1er janvier 70 05:00:00).

Nous continuons à comprendre, et il s'avÚre que ce fichier est stocké dans boot.img , et chaque fois qu'il en sort. Et pour changer la fonctionnalité du fichier init.rc , vous devez faire tout cela .

Mais il existe un moyen plus simple de résoudre ce problÚme. Pour cette méthode, nous pouvons utiliser le script shell suivant (merci à Ryuinferno):

Script 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 


Premiers pas avec le script! Dans mon cas, il s'appellera init.sh.
1. Téléchargez le fichier sur la carte SD de l'appareil mobile:
 adb push /tmp/init.sh /sdcard 

2. Copiez dans la mémoire de l'appareil mobile et définissez les droits nécessaires:
 adb shell su cp /sdcard/init.sh /data/init.sh chmod 777 /data/init.sh 

3. Exécuter pour exécution:
 /data/init.sh 

Et faites attention au journal qui s'affiche. Voici mon journal:
Exécuter le journal
 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 


Comme vous pouvez le voir dans le journal, il n'y a aucune erreur, alors n'hĂ©sitez pas Ă  redĂ©marrer l'appareil! Peut-ĂȘtre que quelqu'un a dĂ©jĂ  travaillĂ© et que vous pouvez trouver le fichier /data/Test.log , mais je ne l'ai pas. VĂ©rifiez le rĂ©pertoire /system/etc/init.d Ă  l'aide de la commande ls :

 00test 01permissive 08setperm 

Comme vous pouvez le voir, les tĂąches ont Ă©tĂ© crĂ©Ă©es avec succĂšs. Vous devrez peut-ĂȘtre encore modifier boot.img , mais vĂ©rifions au dĂ©but, oĂč se trouve le fichier install-recovery.sh avec la commande

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

Comme nous pouvons le voir, nous avons 2 fichiers qui se trouvent Ă  diffĂ©rents endroits. À la date de crĂ©ation, nous pouvons remarquer que le script a crĂ©Ă© le fichier dans le rĂ©pertoire /system/etc/install-recovery.sh , bien que, dans certains cas, il doive peut-ĂȘtre le crĂ©er dans / system / etc. Renommons le fichier en bin et copions le fichier depuis etc:

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


UPD : Veuillez noter que le contexte de sĂ©curitĂ© pour les deux fichiers doit correspondre. Et si vous vous ĂȘtes soudainement perdu lors de la copie (bien qu'en thĂ©orie cela ne devrait pas l'ĂȘtre), vous devrez le restaurer (par exemple, via l'utilitaire chcon ). Voir les informations complĂštes sur le fichier avec ls -lZ :
 ls -lZ /system/etc/install-recovery.sh # -rwxr-xr-x root root u:object_r:system_file:s0 install-recovery.sh 

Ici u: object_r: system_file: s0 correspond aux contextes de sécurité.

Et encore une fois, nous redémarrons l'appareil ... Et maintenant, enfin, le SUCCÈS tant attendu! Le fichier /data/Test.log est apparu!

Une fois que tout fonctionne, allez dans /system/etc/init.d et créez un script shell. Et dedans, lancez simplement notre crond pour exécuter:

 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 

AprÚs le téléchargement, vérifiez si crond a démarré:

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

Et nous pourrions terminer maintenant, mais attendons une minute et voyons s'il y avait un enregistrement dans notre dossier ... Eh bien, comme vous l'avez dĂ©jĂ  compris, encore une fois, rien n'a fonctionnĂ©. Le fait est que ce processus doit ĂȘtre exĂ©cutĂ© Ă  partir d'un super utilisateur. Modifiez le script dans le fichier 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 : Peut-ĂȘtre que dans votre cas, su aura un chemin diffĂ©rent, puis utilisez la commande su et remplacez le chemin par le vĂŽtre.

Maintenant, notre appareil Android prend en charge les tĂąches cron et peut contenir des scripts shell pour un lancement automatique!

Et enfin, le script qui va exécuter notre application, s'il n'est pas dans les processus et enregistrer des informations sur ce qui était sur l'écran principal avant de lancer notre application:

 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/fr468337/


All Articles