使用Android版cron并添加Shell脚本以在设备启动时自动运行



由于移动设备长期以来具有广泛的功能,因此可以轻松地将自动化任务转移给它们。 而且,cron尽可能地适合执行它们。 但是,如果cron在“普通” Linux系统上花费一些时间,则Android设备需要进行更复杂的配置工作。

如果您对自动化主题感兴趣,并且希望在设备启动后立即启动Shell脚本,甚至可以通过计时器启动,那么欢迎您!

前言


我从事Android移动设备的自动化。 在执行自动脚本的过程中,即使使用相同的设备进行测试,也会发生许多无法预料的情况。

最受欢迎的问题:

0.自动化脚本无法满足您的需求。
1.移动应用程序自动下载
2.手机自动重启
3.重新启动后,移动应用程序不会自动启动
4. Wi-Fi模块随机关闭,找不到网络,未连接到网络
5.移动网络突然消失
6.手机进入睡眠模式
7.代理掉线或服务器本身或服务器返回奇怪的响应

因此,您必须不断监视设备并捕获这些不可预见的情况。



因此,我得出的结论是,带有“正确”脚本的cron将使您能够跟踪软件故障并还原自动化脚本或再次运行它。 但事实证明,尽管Android包含Linux内核,但我必须处理一些特殊的细微差别。 因此,让我们开始进行设置!

Cron设置


定制环境


  1. 安装adb以使用USB线通过外壳访问设备。
  2. 我们打开“面向开发人员 ”部分。 为此,请转到“ 关于电话”部分,然后单击“ 内部版本号”或类似名称。
  3. 我们转到面向开发人员的部分,然后将其打开。 我们将设备连接到计算机,并允许在此计算机上访问该设备。
  4. 为您的设备添加root 。 最常见的选项是SuperSuMagiskKingroot 。 转到w3bsit3-dns.com并找到您设备的root选项。 不幸的是,没有普遍的根源。
  5. 我们安装了BusyBox (例如,它也在w3bsit3-dns.com上),因为它仅包含一个cron程序。

手动开始设定


  1. 我们使用adb shell连接到电话(如果adb未在您的环境变量中注册,请添加完整路径。
  2. 使用su命令进入root模式
  3. 我们检查cron程序是否存在,并使用crond -h命令查看设置

执行结果
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 


从最后一行可以看到,默认指令应存储在目录/ var / spool / cron / crontabs中 ,该目录不会自动创建,并且如果我们运行命令
 crond -b 
然后检查该过程是否开始
 ps | grep crond 
,那么它可能不存在,因为 他没有得到任何指示。 所以我们执行命令
 crond -b -fd0 
看看是什么原因。 您很可能会遇到类似的错误:
crond: can't change directory to '/var/spool/cron/crontabs': No such file or directory 。 在这种情况下,这是正常的,因为 将来,我们自己将指示crontab可执行文件的路径。

4.创建一个简单的crontab文件:

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

现在我们有一个任务,每分钟将单词文本添加到文件/sdcard/test.txt中
我们推出:
 crond -b -fd0 -c /data/crontab 
并获得以下日志:

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

当然,这有点令人惊讶,因为如果我们执行whoami命令,它将作为结果返回root

5.添加root用户,因为crond会询问:

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

由于缺少此文件,我意识到在Android系统中根本不涉及该文件。 如果您确定将crontab文件存储在何处,则可以用所需的行替换/ system / etc / crontabs 。 再次运行命令

 crond -b -fd0 -c /data/crontab 

我们得到以下信息:

 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 

尽管根据日志,该任务已在crond中注册,但是在我的情况下,未创建文件。 这个问题可以很简单地解决:

 mkdir -p /system/etc/crontabs 

好吧,他想要一个目录存在于此,我们该禁止他! 我们再次开始,看到:

 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 

错误消失了,并出现了以下问题:子运行中/ system / bin / sh 。 最后,cron已成功结束,您可以继续进行第二部分!

自动shell脚本下载


Linux系统有一个init.d目录,该目录负责在系统引导后立即自动启动,所以让我们尝试一下!

1.检查此目录在您的设备上是否存在(这是/etc/init.d/system/etc/init.d-这是相同的已安装分区等)。 就我而言,事实并非如此。 好吧,然后创建:

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

现在在其中添加一些简单的脚本,例如:

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

我们重新启动设备,看看是否发生了奇迹...不幸的是,我的文件没有出现。

我们将进一步检查系统,并寻找一些可以在启动后运行脚本的初始化文件。 我的设备上的/init.rc中有一个文件。 好吧,让我们尝试更改它并重新启动设备:

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

但是没有再次创建该文件。 我们去查看文件/init.rc ,我们的记录消失了,文件似乎没有变化,因为 创建日期非常奇怪(以我为例,70年1月1日,05:00:00)。

我们继续理解,事实证明该文件存储在boot.img中 ,并且每次退出该文件时都会存储。 为了更改init.rc文件的功能, 需要做所有一切。

但是,有一种更简单的方法可以帮助解决此问题。 对于这种方法,我们可以使用以下shell脚本(感谢Ryuinferno):

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 


脚本入门! 在我的情况下,它将称为init.sh。
1.将文件下载到移动设备的SD卡中:
 adb push /tmp/init.sh /sdcard 

2.复制到移动设备的内存中并设置必要的权限:
 adb shell su cp /sdcard/init.sh /data/init.sh chmod 777 /data/init.sh 

3.运行执行:
 /data/init.sh 

并注意显示的日志。 这是我的日志:
运行日志
 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 


从日志中可以看到,没有错误,请随时重新启动设备! 也许有人已经在工作,您可以找到/data/Test.log文件,但我没有。 使用ls命令检查/system/etc/init.d目录:

 00test 01permissive 08setperm 

如您所见,任务已成功创建。 您可能仍然需要更改boot.img ,但是让我们在开始时检查一下,其中的install-recovery.sh文件在以下位置:

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

如我们所见,我们有2个文件位于不同的位置。 在创建日期之前,我们可以注意到该脚本在/system/etc/install-recovery.sh目录中创建了该文件,尽管在某些情况下,它应该在/ system / etc中创建该文件 让我们将文件重命名为bin并从etc复制文件:

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


UPD :请注意,两个文件的安全性上下文必须匹配。 而且,如果您在复制时突然迷路(虽然从理论上讲应该不是),则需要将其还原(例如,通过chcon实用程序)。 使用ls -lZ查看完整的文件信息:
 ls -lZ /system/etc/install-recovery.sh # -rwxr-xr-x root root u:object_r:system_file:s0 install-recovery.sh 

在这里u:object_r:system_file:s0是安全上下文。

再次,我们重新启动设备...现在,终于,期待已久的成功! 文件/data/Test.log已经出现!

一切正常后,转到/system/etc/init.d并创建一个shell脚本。 然后在其中运行我们的crond以执行:

 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 

下载后,检查crond是否已启动:

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

现在可以结束了,但是让我们等待一分钟,看看我们的文件中是否有记录...好了,正如您已经了解的那样,什么也没起作用。 事实是,此过程需要从超级用户运行。 更改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 :也许在您的情况下, su将具有不同的路径,然后使用su命令并用您的路径替换该路径。

现在,我们的Android设备支持cron任务,并且可能包含用于自动启动的shell脚本!

最后,将运行我们的应用程序的脚本(如果不在进程中)并在启动我们的应用程序之前保存有关主屏幕上内容的信息:

 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/zh-CN468337/


All Articles