Due to the fact that mobile devices have long had extensive functionality, automation tasks can be easily transferred to them. And, as well as possible, cron is just as good for executing them. But if cron takes a little time in "regular" Linux systems, then an Android device requires more complicated work to configure it.
If you are interested in the topic of automation and you want your shell scripts to run immediately after the device boots up, and even could start on a timer - welcome to the cat!
Foreword
I am engaged in the automation of mobile devices for Android. And during the execution of automatic scripts, many unforeseen situations occur, even if the same devices are used for testing.
Most popular problems:
0. The automation script does not do what you wanted.
1. The mobile application is automatically downloaded
2. Automatic reboot of the phone
3. The mobile application does not automatically start after a restart
4. The Wi-Fi module randomly turns off, does not find the network, does not connect to the network
5. Mobile network suddenly disappeared
6. The phone went into sleep mode
7. The proxy dropped or the server itself or the server returned a strange response
Because of this, you have to constantly monitor the device and catch these unforeseen situations.
Thus, I came to the conclusion that cron with the "correct" scripts will allow you to track software failures and restore the automation script or run it again. But as it turned out, although Android contains the Linux kernel, there are special nuances that I had to deal with. So let's get started on setting up!
Cron setup
Customize the environment
- Install adb to access the device through the shell using a usb wire.
- We open the section For developers . To do this, go to the About phone section and make a few clicks on the Build number or something similar.
- We go to the section For developers and turn it on. We connect the device to the computer and allow access on this computer to this device.
- Add root for your device. The most common options are SuperSu , Magisk, and Kingroot . Go to w3bsit3-dns.com and find the root option for your device. Unfortunately, there is no universal root.
- We install BusyBox (it is also on w3bsit3-dns.com, for example), since it just contains a cron program.
Manual start setting
- We connect to the phone using adb shell (if adb is not registered in your environment variable, then add the full path.
- Go to root mode with the su command
- We check the presence of the cron program and see the settings using the crond -h command
execution result 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
As you can see from the last line, the default instructions should be stored in the directory
/ var / spool / cron / crontabs , which is not automatically created and if we run the command
crond -b
and then check if the process started through
ps | grep crond
, then it may not be there, because he could not get any instructions. So let's execute the command
crond -b -fd0
and see what is the reason. Most likely you will have a similar error:
crond: can't change directory to '/var/spool/cron/crontabs': No such file or directory
. In this case, this is normal, because in the future, we ourselves will indicate the path to the crontab executable file.
4. Create a simple crontab file:
mkdir /data/crontab echo "*/1 * * * * echo 'text' >> /sdcard/test.txt" > /data/crontab/root
Now we have a task that will add the word
text every minute to the
/sdcard/test.txt file
We launch:
crond -b -fd0 -c /data/crontab
and get the following log:
crond: crond (busybox 1.29.2-Stericson) started, log level 0 crond: ignoring file 'root' (no such user) ...
Of course, it is a little surprising, because if we execute the
whoami command, then as a result it will return
root .
5. Add the root user, since crond asks:
mount -o remount,rw /system; echo "root:x:0:0::/system/etc/crontabs:/system/bin/sh" >> /system/etc/passwd; mount -o remount,ro /system;
Due to the lack of this file, I realized that in the Android system it is not involved at all. If you are sure where you will store your crontab files, then you can replace the line
/ system / etc / crontabs with the one you need. Run the command again
crond -b -fd0 -c /data/crontab
And we get the following:
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
Although, according to the log, the task was registered in crond, but in my case the file was not created. The problem can be solved very simply:
mkdir -p /system/etc/crontabs
Well, he wants a directory to exist there, who are we to forbid him! We start again and see:
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
The errors went away and the line
crond: child running / system / bin / sh appeared . Finally, cron has been successfully wound up, and you can move on to the second part!
Automatic shell script loading
The Linux system has an
init.d directory that is responsible for autostart immediately after the system boots, so let's try this way!
1. Check if this directory exists on your device (this is
/etc/init.d or
/system/etc/init.d - this is the same mounted partition etc). In my case, it is not. Well, then create:
mount -o remount,rw /system mkdir /system/etc/init.d chmod 0755 /system/etc/init.d mount -o remount,ro /system
Now add some simple script there, for example:
echo "echo 'Init.d is working !!!' >> /sdcard/init_test.log" > /system/etc/init.d/90my_script chmod 777 /system/etc/init.d/90my_script
We reboot the device and see if a miracle happened ... Unfortunately, my file did not appear.
We examine the system further and look for some init file that can run scripts after launch. I had a file in
/init.rc on my device. Well, let's try changing it and rebooting the device:
mount -o remount,rw / echo "echo 'Init.d is working !!!' >> /sdcard/init_test.log" >> /init.rc mount -o remount,ro / reboot
But the file was not created again. We go to look at the
/init.rc file and our record disappeared and the file did not seem to change, because the creation date is quite strange (in my case, Jan 1, 70 05:00:00).
We continue to understand, and it turns out that this file is stored in
boot.img , and each time it gets from it. And in order to change the functionality of the
init.rc file,
you need to do all
this .
But there is an easier way to help solve this problem. For this method, we can use the following shell script (say thanks to Ryuinferno):
Getting started with the script! In my case, it will be called init.sh.
1. Download the file to the sdcard of the mobile device:
adb push /tmp/init.sh /sdcard
2. Copy to the memory of the mobile device and set the necessary rights:
adb shell su cp /sdcard/init.sh /data/init.sh chmod 777 /data/init.sh
3. Run for execution:
/data/init.sh
And pay attention to the log, which is displayed. Here is my log:
Run 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
As you can see from the log, there are no errors, so feel free to reboot the device! Maybe someone already worked and you could find the
/data/Test.log file, but I donβt have it. Check the directory
/system/etc/init.d using the
ls command :
00test 01permissive 08setperm
As you can see, the tasks have been successfully created. You may still have to change
boot.img , but let's check at the beginning, where is the
install-recovery.sh file with the command
find / -name "install-recovery.sh" ... /system/bin/install-recovery.sh /system/etc/install-recovery.sh ...
As we can see, we have 2 files that lie in different places. By the date of creation, we can notice that the script created the file in the directory
/system/etc/install-recovery.sh , although, perhaps, in some cases it should create it in
/ system / etc. Let's rename the file to bin and copy the file from etc:
mount -o remount,rw /system mv /install-recovery.sh /system/bin/install-recovery2.sh cp /install-recovery.sh /system/bin/
And again we reboot the device ... And now, finally, the long-awaited SUCCESS! The file
/data/Test.log has appeared!
Once everything works, go to
/system/etc/init.d and create a shell script. And in it, just run our crond to execute:
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
After downloading, check if crond has started:
ps | grep crond root 414 1 9532 236 hrtimer_na 000dcf90 S crond
And we could finish it already, but let's wait a minute and see if there was a record in our file ... Well, as you already understood, again, nothing worked. The fact is that this process needs to be launched from a super user. Change the script in the
99cronstart file:
echo "#!/system/bin/sh su -c crond -b -L /sdcard/error.log -c /data/crontab" > /system/etc/init.d/99cronstart reboot
Now our Android device supports cron tasks and may contain shell scripts for automatic launch!
And finally, a script that will run our application if it is not in the processes and save information about what was on the main screen before launching our 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