
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
- Instale o adb para acessar o dispositivo através do shell usando um fio USB.
- 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.
- Vamos para a seção Para desenvolvedores e ativamos. Conectamos o dispositivo ao computador e permitimos acesso neste computador a este dispositivo.
- 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.
- 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
- 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.
- Vá para o modo raiz com o comando su
- Verificamos a presença do programa cron e vemos as configurações usando o comando crond -h
resultado de execuçãocrond: 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.txtLanç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):
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
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