26

I can't find answer to my question: Is it possible to run crontab to reboot Android using busybox (or other means)

Tried to run crontab, and it complain about unknown uid 0.

Tried to run reboot, and it does nothing.

Or I am asking for the impossible right now?

Maroun
  • 94,125
  • 30
  • 188
  • 241
see2851
  • 627
  • 1
  • 9
  • 13
  • http://stackoverflow.com/questions/13063106/how-to-install-busybox-on-android-emulator-android-2-3-3 – Sam May 25 '13 at 08:45

7 Answers7

26

Requirements

  1. Root access: for superuser commads like reboot, or init.d config. Crond can still run under normal user privs.

  2. Busybox: for 'crond' service

  3. (Optional) init.d support: to start 'crond' service at boot. Or start via Magisk post-fs-data.d script.

Creating cronjob

Create the cronjob file in directory /data/crontab/ (it could be any accessible directory even in sdcard) with filename 'root'. Write your cronjob inside the file 'root'.

echo ' 
53 * * * * reboot' >> /data/crontab/root

Test without rebooting

Now open any terminal emulator in device and run the following commands..

su -
crond -b -c /data/crontab

Now the crond service will start, to check type pgrep -l crond or ps | grep crond

Start crond at boot

create a file at /system/etc/init.d with executable permission:

echo '   
crond -b -c /data/crontab' > /system/etc/init.d/crond

chmod +x /system/etc/init.d/crond

Example cronjobs

53 * * * * reboot

Will reboot your device on 53rd minute of every hour.

Note: 1. If you modify crontab, remember to restart crond daemon after killing the existing one.

  1. If the crond is not obeying your timezone, you might need to update the tzdata in your device.

  2. Better to test with */1 * * * * to see if it is working.

peer
  • 4,171
  • 8
  • 42
  • 73
Seff
  • 1,546
  • 1
  • 17
  • 19
  • In section `Start crond at boot` command should not be `crond -b -c /data/crond` but `crond -b -c /data/cronjob` – zen Jun 06 '15 at 12:29
  • `/system` was a read only file system for me so I had to enclose the creation of `/system/etc/init.d/crond` with `mount -o rw,remount /system` and `mount -o ro,remount /system` I also got `bad mode` on `chmod +x` so I had to use `chmod 766` instead – peer May 17 '20 at 15:15
4

This is a complement to Seff's answer above. Couldn't place it in a comment because it's too long

/system/etc/init.d is not always guaranteed to work. In my case it did not. There are other methods mentioned in the following link in case this one didn't work for you https://android.stackexchange.com/questions/6558/how-can-i-run-a-script-on-boot/196785

Even then crond didn't run any job for me. To debug the errors I killed the running instance pkill crond and ran it like that

crond -f -d0 -c /data/crontab/

This make crond run in forground and print all the debugging information. When I ran it like that I got this warning

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

So I had to create a passwd file with entry for root

 echo 'root:x:0:0:root:/data:/system/bin/sh' > /system/etc/passwd                                                                                                         

Even then, it still failed with error like

crond:  job: 0 /system/bin/ls
crond: child running /bin/sh
crond: can't execute '/bin/sh' for user root

Please note that no where in my cronjob did I mentioned "/bin/sh". This seems to be hard coded in the binary.

Next I added the following lines to my init script

/system/xbin/mount -o remount,rw /
/system/xbin/ln -s /system/bin/ /bin
/system/xbin/mount -o remount,ro /

and that's it. It worked fine after that

Ramast
  • 7,157
  • 3
  • 32
  • 32
  • This worked perfectly for me. All of the steps you mentioned were required. Thanks! – CyberInferno Feb 27 '19 at 04:28
  • Same here! Thank you very much! – skjorrface Sep 22 '19 at 12:43
  • What/Where is the init script? – Frak May 03 '20 at 01:17
  • Please refer to Seff's answer above. My answer is just a complementary to his answer – Ramast May 04 '20 at 17:59
  • Is it safe to put root user into passwd file? Can it be exploited to log in as root user? – Politechniczny May 14 '22 at 13:30
  • the entry I've created has no password which means it's impossible to use for logging in. Besides since that file didn't exist, it's safe to assume that Android doesn't even look at it. This is there because crond app is linux based (not Android) and so it's expecting that file to exist. Rest of the system would ignore it – Ramast May 16 '22 at 03:06
1

if you get error "read only file system", you need to remount the /system as read-write:

mount -o rw,remount /dev/stl12 /system

When done, remount it as read-only:

mount -o ro,remount /dev/stl12 /system
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
janis
  • 19
  • 1
0

You will likely need to set your TimeZone and add a root user. Adding a root user can be done like this:

echo "root:x:0:0::/system/etc/crontabs:/system/bin/sh" > /system/etc/passwd

Getting the right TimeZone string is odd. Set the TZ environment variable to the timezone string and make sure crond gets it. I have it under control of a GUI environment, and use the following for getting the TimeZone (may not be correct as I've not tested it on other timezones yet).

public static String findTZS() {
    String date = ZooGate.readShellCommand("date");
    String[] elements = date.split(" ");
    String label = elements[4];
    TimeZone tz = Calendar.getInstance().getTimeZone();
    boolean dlt = tz.useDaylightTime();
    int offset = tz.getDSTSavings()/600000;
    DateFormatSymbols dfs = DateFormatSymbols.getInstance();
    String[][] z = dfs.getZoneStrings();
    for (String[] za: z) {
        if (dlt) {
            if (za[4].equals(label)) {
                return za[2] + offset + za[4];
            } else if (za[2].equals(label)) {
                return za[2] + offset + za[4];
            }
        }
    }
    return "UTC";
}

Also be sure your crontab is named for the user (root) and also owned by that user. If you set the crontab on your internal storage so that you can edit it with Android text editors, you can make it a symlink to /data/media/0. I use /system/etc/crontabs/root -> /data/media/0/Cron/master

You use /data/media and /storage or /sdcard because the latter is a FUSE filesystem that hides the underlying Unix file system permissions and ownership, so you need to set the ownership on the real filesystem in /data.

If you have an older Android that uses Fat or YAFFS or whatever for the internal storage then you might have to keep your crontabs in /system

Beware that cron doesn't always run on time under Android since it likes to oversleep.

Evan Langlois
  • 4,050
  • 2
  • 20
  • 18
  • You should use `>>` instead of `>` when adding the root user to avoid overwriting the `passwd` file: `echo "root:x:0:0::/system/etc/crontabs:/system/bin/sh" >> /system/etc/passwd` – András Korn Sep 16 '18 at 08:46
  • @András Korn Until recently, Android didn't use that file at all. It now claims to be autogenerated, so beware that changes may not stick – Evan Langlois Sep 17 '18 at 09:51
  • Oh. Good to know. FWIW, on my phone it already contained the root user, so no change was necessary. – András Korn Sep 18 '18 at 10:34
0

This app works quite well:

https://f-droid.org/packages/it.faerb.crond/

The cron format is the "user" format not the "system" format and all users run as root.

This is how I do a daily reboot of my LineageOS 18.1 Android install:

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

1 11 * * * /system/bin/reboot
KJ7LNW
  • 1,437
  • 5
  • 11
0

I am going to leave this here for anyone who needs this for a non-rooted device.

Before proceeding a caveat:

  • This method will be using the termux app, which will need to be running constantly in the background to execute the crons

Install the Termux android app, instructions on how are available on their GitHub page.

Step by step after installing termux, gotten from this Reddit thread:

  • pkg install cronie termux-services (restart termux after this step)
  • sv-enable crond

Run crontab -e (like you would normally do on a Linux machine) and add your cron.

0

Method using Termux autostarting on boot with Macrodroid, and keeping running on background. I use it on a rooted device, but I don't see why it shouldn't work on any non-rooted device, too :

  • Install Termux from Playstore, or for older Android 5.x.x/6.x.x machines install the last working version termux-v0.79-offline-bootstraps.apk, for example from https://archive.org/download/termux-repositories-legacy/

  • Note if you have an older Android 5-6 and use termux-v0.79-offline-bootstraps.apk: you must tweak a little the repositories list:

    $ nano  /data/data/com.termux/files/usr/etc/apt/sources.list
    # Comment out:
    #deb https://termux.net stable main
    
    #Add:    
    deb https://packages.termux.dev/termux-main-21 stable main 
    

    Remove repositories games & science

    $ pkg remove science-repo
    $ pkg remove game-repo
    

    Update (choose default to all answers - press Enter)

    $ pkg update
    
  • In order to have Termux launched on boot, I use Macrodroid: works on practically every old or new Android phone/tablet I have ever used. Create a new Macro: Triggers: (a)'Device boot', Actions: (a)'Launch Termux', (b)'Wait 10 seconds', (c)'Launch Home Screen'. (Screenshot from Macrodroid). Check that it works on reboot. Termux should be now launched and put on background.

  • In version termux-v0.79-offline-bootstraps.apk (which I use), crond seems to installed by default. Try: $ crond, and check if daemon crond is running with $ pgrep crond. If you have problems, please check elsewhere how to install crond in Termux.

  • In order to have crond executed on Termux-launch, add a startup-script (e.g. startup-crond) in directory /data/data/com.termux/files/usr/etc/profile.d/ . All scripts in this directory get sourced in the start-script of bash on every new login.

    Contents of /data/data/com.termux/files/usr/etc/profile.d/startup-crond

    if pgrep "crond" >/dev/null; then
       echo "crond is already running"
    else 
       echo "Starting crond ..." && crond && echo "[OK]"
    fi
    

    Make sure file is executable: $ chmod 775 startup-crond

  • In this way, every time Termux is launched, .../usr/etc/profile.d/startup-crond witll check if crond is running, and if not the daemon will be launched. An '[OK]' message confirms that everything worked.

  • Add your crontab entries in termux with $ crontab -e (uses vi editor). This will create a file with the user-name of Termux-App in /data/data/com.termux/files/usr/var/spool/cron/crontabs/. The name of the crontab is the user-name of Termux. You can confirm with $ whoami. If you don't like vi, you can see/edit the contents of the above file manually as well. e.g. with nano.

  • Note that, as other authors have mentioned, this is user-level crontab, it has syntax * * * * * my-script. Unlike Linux's system /etc/crontab don't add a "user-name" entry before my-script!. In fact, there is no system /etc/crontab in Termux, only user-level crontabs.

  • If you want to do more complex crontab entries, for example having multiple separate crontab-files, you can tell crontab to get as input not a single file, but stdin with $ crontab -. I like to have multiple separate files named "XXXX.cron" in the above mentioned directory, and have them all sent to crontab:

    $ cat /data/data/com.termux/files/usr/var/spool/cron/crontabs/*.cron | crontab -
    
  • You can add this one-liner to the above-mentioned .../usr/etc/profile.d/startup-crond script. Check any time the cumulative crontab entries with $ crontab -l

Loosely related to the question, but still interesting when working through ssh:

  • I prefer doing command-line stuff on Termux using my keyboard from a desktop through ssh, and not on the touchscreen (in case somebody is interested, summary for a quick-setup but not the most secure: $ pkg install openssh, create a password with $ passwd, launch $ sshd, find your android's ip with $ ifconfig, look under wlan0 the entry: inet 192.168.XXX.XXX, login to your android device from a desktop with $ ssh 192.168.XXX.XXX -p 8022). When inside Termux I also strongly suggest exploring directories with Midnight-Commander: $ pkg install mc
  • Side effect of the above method: every time you login in Termux through ssh, you will have .../usr/etc/profile.d/startup-crond launched again, with a reminder that crond is running. Personally, it does not bother me.
vkarantz
  • 1
  • 1