Trabalhando com o cron para Android e adicionando um script de shell à execução automática quando o dispositivo é inicializado



Devido ao fato de os dispositivos móveis terem longa funcionalidade, as tarefas de automação podem ser facilmente transferidas para eles. E, da melhor maneira possível, o cron é tão bom para executá-los. Mas se o cron demorar um pouco em sistemas Linux "comuns", um dispositivo Android precisará de um trabalho mais complicado para configurá-lo.

Se você está interessado no tópico de automação e deseja que seus scripts de shell sejam executados imediatamente após a inicialização do dispositivo, e ainda pode iniciar em um temporizador - bem-vindo ao gato!

Prefácio


Estou envolvido na automação de dispositivos móveis para Android. E durante a execução de scripts automáticos, muitas situações imprevistas ocorrem, mesmo que os mesmos dispositivos sejam usados ​​para teste.

Problemas mais populares:

0. O script de automação não faz o que você queria.
1. O aplicativo móvel é baixado automaticamente
2. Reinicialização automática do telefone
3. O aplicativo móvel não inicia automaticamente após uma reinicialização
4. O módulo Wi-Fi desliga aleatoriamente, não encontra a rede, não se conecta à rede
5. A rede móvel desapareceu repentinamente
6. O telefone entrou no modo de suspensão
7. O proxy caiu ou o próprio servidor ou o servidor retornou uma resposta estranha

Por esse motivo, é necessário monitorar constantemente o dispositivo e capturar essas situações imprevistas.



Assim, cheguei à conclusão de que o cron com os scripts "corretos" permitirá rastrear falhas de software e restaurar o script de automação ou executá-lo novamente. Mas, como se viu, embora o Android contenha o kernel do Linux, há nuances especiais com as quais eu tive que lidar. Então, vamos começar a configurar!

Configuração do Cron


Personalize o ambiente


  1. Instale o adb para acessar o dispositivo através do shell usando um fio USB.
  2. Abrimos a seção Para desenvolvedores . Para fazer isso, vá para a seção Sobre o telefone e faça alguns cliques no número da versão ou algo semelhante.
  3. Vamos para a seção Para desenvolvedores e ativamos. Conectamos o dispositivo ao computador e permitimos acesso neste computador a este dispositivo.
  4. Adicione raiz ao seu dispositivo. As opções mais comuns são SuperSu , Magisk e Kingroot . Acesse w3bsit3-dns.com e encontre a opção de raiz para o seu dispositivo. Infelizmente, não há raiz universal.
  5. Instalamos o BusyBox (também está em w3bsit3-dns.com, por exemplo), pois ele contém apenas um programa cron.

Configuração manual de início


  1. Nós nos conectamos ao telefone usando o shell adb (se o adb não estiver registrado na sua variável de ambiente, adicione o caminho completo.
  2. Vá para o modo raiz com o comando su
  3. Verificamos a presença do programa cron e vemos as configurações usando o comando crond -h

resultado de execução
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 você pode ver na última linha, as instruções padrão devem ser armazenadas no diretório / var / spool / cron / crontabs , que não é criado automaticamente e se executarmos o comando
 crond -b 
e verifique se o processo foi iniciado
 ps | grep crond 
, então pode não estar lá, porque ele não conseguiu nenhuma instrução. Então, vamos executar o comando
 crond -b -fd0 
e veja qual é o motivo. Provavelmente você terá um erro semelhante:
crond: can't change directory to '/var/spool/cron/crontabs': No such file or directory . Nesse caso, isso é normal, porque no futuro, nós mesmos indicaremos o caminho para o arquivo executável crontab.

4. Crie um arquivo crontab simples:

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

Agora temos uma tarefa que a cada minuto adicionará a palavra texto ao arquivo /sdcard/test.txt
Lançamos:
 crond -b -fd0 -c /data/crontab 
e obtenha o seguinte log:

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

Claro, é um pouco surpreendente, porque se executarmos o comando whoami, ele retornará a raiz como resultado.

5. Adicione o usuário root, pois o crond pergunta:

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

Devido à falta desse arquivo, percebi que no sistema Android ele não está envolvido. Se você tiver certeza de onde armazenará seus arquivos crontab, poderá substituir a linha / system / etc / crontabs pela que você precisa. Execute o comando novamente

 crond -b -fd0 -c /data/crontab 

E temos o seguinte:

 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 

Embora, de acordo com o log, a tarefa tenha sido registrada em crond, mas no meu caso o arquivo não foi criado. O problema pode ser resolvido de maneira muito simples:

 mkdir -p /system/etc/crontabs 

Bem, ele quer que exista um diretório lá, quem somos nós para proibi-lo! Começamos novamente e 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 

Os erros desapareceram e a linha crond: child running / system / bin / sh apareceu . Finalmente, o cron foi encerrado com êxito e você pode passar para a segunda parte!

Download automático de script de shell


O sistema Linux possui um diretório init.d responsável pela inicialização automática imediatamente após a inicialização do sistema, então vamos tentar desta maneira!

1. Verifique se este diretório existe no seu dispositivo (este é /etc/init.d ou /system/etc/init.d - esta é a mesma partição montada etc). No meu caso, não é. Bem, então crie:

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

Agora adicione algum script simples lá, por exemplo:

 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 o dispositivo e verificamos se houve um milagre ... Infelizmente, meu arquivo não apareceu.

Examinamos o sistema mais detalhadamente e procuramos algum arquivo init que possa executar scripts após o lançamento. Eu tinha um arquivo no /init.rc no meu dispositivo. Bem, vamos tentar alterá-lo e reiniciar o dispositivo:

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

Mas o arquivo não foi criado novamente. Vamos examinar o arquivo /init.rc e nosso registro desapareceu e o arquivo não pareceu mudar, porque a data de criação é bastante estranha (no meu caso, 1º de janeiro de 70 05:00:00).

Continuamos a entender, e acontece que esse arquivo é armazenado no boot.img e cada vez que sai dele. E para alterar a funcionalidade do arquivo init.rc , você precisa fazer tudo isso .

Mas existe uma maneira mais fácil de ajudar a resolver esse problema. Para este método, podemos usar o seguinte script de shell (diga obrigado 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 


Começando com o script! No meu caso, será chamado init.sh.
1. Faça o download do arquivo para o sdcard do dispositivo móvel:
 adb push /tmp/init.sh /sdcard 

2. Copie para a memória do dispositivo móvel e defina os direitos necessários:
 adb shell su cp /sdcard/init.sh /data/init.sh chmod 777 /data/init.sh 

3. Execute para execução:
 /data/init.sh 

E preste atenção ao log que é exibido. Aqui está o meu log:
Executar log
 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 você pode ver no log, não há erros, portanto, fique à vontade para reiniciar o dispositivo! Talvez alguém já tenha trabalhado e você possa encontrar o arquivo /data/Test.log , mas eu não o tenho. Verifique o diretório /system/etc/init.d usando o comando ls :

 00test 01permissive 08setperm 

Como você pode ver, as tarefas foram criadas com sucesso. Talvez você ainda precise alterar o arquivo boot.img , mas vamos verificar no início, onde está o arquivo install-recovery.sh com o comando

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

Como podemos ver, temos 2 arquivos que estão em lugares diferentes. Até a data de criação, podemos notar que o script criou o arquivo no diretório /system/etc/install-recovery.sh , embora, talvez, em alguns casos, ele seja criado em / system / etc. Vamos renomear o arquivo para bin e copiar o arquivo de etc:

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


UPD : Observe que o contexto de segurança para os dois arquivos deve corresponder. E se você se perder repentinamente durante a cópia (embora em teoria isso não deva ser), será necessário restaurá-lo (por exemplo, através do utilitário chcon ). Veja as informações completas do arquivo com ls -lZ :
 ls -lZ /system/etc/install-recovery.sh # -rwxr-xr-x root root u:object_r:system_file:s0 install-recovery.sh 

Aqui u: object_r: system_file: s0 são contextos de segurança.

E novamente reiniciamos o dispositivo ... E agora, finalmente, o tão esperado SUCESSO! O arquivo /data/Test.log apareceu!

Depois que tudo funcionar, vá para /system/etc/init.d e crie um script de shell. E nele, basta executar nossa tarefa para executar:

 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 

Após o download, verifique se o crond foi iniciado:

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

E poderíamos terminar agora, mas vamos esperar um minuto e ver se havia um registro em nosso arquivo ... Bem, como você já entendeu, novamente, nada funcionou. O fato é que esse processo precisa ser executado a partir de um super usuário. Altere o script no arquivo 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 : Talvez no seu caso su tenha um caminho diferente, use o comando su e substitua o caminho pelo seu.

Agora, o nosso dispositivo Android suporta tarefas cron e pode conter scripts de shell para inicialização automática!

E, finalmente, o script que executará nosso aplicativo, se não estiver nos processos e salve informações sobre o que estava na tela principal antes de iniciar nosso aplicativo:

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


All Articles