如何在Android中使用crontab?

27

我找不到答案,想问一个问题:是否可以使用busybox(或其他方式)来运行crontab以重新启动Android?

尝试运行crontab时,它报告未知的uid 0。

尝试运行reboot,但它没有任何作用。

还是说我现在在寻求不可能的东西?


http://stackoverflow.com/questions/13063106/how-to-install-busybox-on-android-emulator-android-2-3-3 - Sam
7个回答

27

需求

  1. Root访问权限:用于超级用户命令,例如重启或init.d配置。Crond仍然可以在普通用户特权下运行。

  2. Busybox:用于'crond'服务

  3. (可选) init.d支持:启动引导时的'crond'服务。或通过Magisk post-fs-data.d脚本启动。

创建定期作业

在目录/data/crontab/(甚至可以是sdcard中的任何可访问目录)中创建cronjob文件,并将文件名命名为“root”。 在文件“root”中编写您的cronjob。

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

无需重启即可测试

现在在设备上打开任何终端仿真器并运行以下命令...

su -
crond -b -c /data/crontab

现在将启动crond服务,要检查请键入pgrep -l crondps | grep crond

开机启动crond

在/system/etc/init.d创建一个带有可执行权限的文件:

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

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

示例cron作业

53 * * * * reboot

将在每小时的第53分钟重新启动您的设备。

注意: 1. 如果您修改了crontab,请记得在杀死现有的crond后重新启动守护程序。

  1. 如果crond没有遵守您的时区,您可能需要在设备上更新tzdata。

  2. 最好使用 */1 * * * * 进行测试以查看是否正常工作。


在“启动时启动crond”部分,命令不应该是“crond -b -c /data/crond”,而应该是“crond -b -c /data/cronjob”。 - zen
“/system” 对我来说是只读文件系统,所以我不得不用“mount -o rw,remount /system”和“mount -o ro,remount /system”来包含“/system/etc/init.d/crond”的创建。我还遇到了“chmod +x”的“bad mode”问题,所以我不得不使用“chmod 766”。 - peer

4
这是对Seff上面答案的补充。/system/etc/init.d不能保证总是有效,至少在我的情况下是无效的。如果您的情况也是如此,请参阅以下链接中提到的其他方法:https://android.stackexchange.com/questions/6558/how-can-i-run-a-script-on-boot/196785 即使如此,crond对我也没用。为了调试错误,我杀死了正在运行的实例pkill crond并像那样运行它。
crond -f -d0 -c /data/crontab/

这将使crond在前台运行并打印所有调试信息。当我像这样运行它时,我收到了这个警告。
crond: crond (busybox 1.27.2-Stericson) started, log level 0
crond: ignoring file 'root' (no such user)

所以我必须创建一个包含root条目的passwd文件。

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

即使如此,仍然会出现错误,例如:
crond:  job: 0 /system/bin/ls
crond: child running /bin/sh
crond: can't execute '/bin/sh' for user root

请注意,在我的cronjob中没有提到“/bin/sh”。这似乎是二进制文件中硬编码的。
接下来,我在我的init脚本中添加了以下几行。
/system/xbin/mount -o remount,rw /
/system/xbin/ln -s /system/bin/ /bin
/system/xbin/mount -o remount,ro /

就是这样。之后一切都工作正常。


这对我来说完美地运作了。你提到的所有步骤都是必需的。谢谢! - CyberInferno
一样!非常感谢! - skjorrface
初始化脚本在哪里? - Frak
请参考Seff上面的答案。我的回答只是对他的回答的补充。 - Ramast
将root用户放入passwd文件中是否安全?是否能够利用它作为root用户登录? - Politechniczny
我创建的条目没有密码,这意味着无法用于登录。此外,由于该文件不存在,可以安全地假定Android甚至不会查看它。这是因为crond应用程序基于Linux(而不是Android),因此它期望该文件存在。系统的其余部分将忽略它。 - Ramast

1
如果您遇到“只读文件系统”错误,您需要将/system重新挂载为可读写状态:
mount -o rw,remount /dev/stl12 /system

完成后,将其重新挂载为只读:
mount -o ro,remount /dev/stl12 /system

0

你可能需要设置你的时区并添加一个root用户。像这样添加一个root用户:

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

获取正确的时区字符串有些奇怪。将TZ环境变量设置为时区字符串,并确保crond获得它。我将其控制在GUI环境下,并使用以下内容获取时区(可能不正确,因为我尚未在其他时区上进行测试)。

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";
}

同时确保您的crontab以用户(root)命名,并由该用户拥有。如果您将crontab设置在内部存储上,以便您可以使用Android文本编辑器进行编辑,则可以将其创建为/data/media/0的符号链接。我使用/system/etc/crontabs/root -> /data/media/0/Cron/master

您可以使用/data/media和/storage或/sdcard,因为后者是一个FUSE文件系统,它隐藏了底层的Unix文件系统权限和所有权,因此您需要在/data中设置真实文件系统的所有权。

如果您使用的是使用Fat或YAFFS或其他用于内部存储的旧版Android,则可能必须将crontabs保留在/system中。

请注意,在Android下,cron不总是按时运行,因为它喜欢睡过头。


在将根用户添加到系统时,应该使用>>而不是>,以避免覆盖passwd文件:echo "root:x:0:0::/system/etc/crontabs:/system/bin/sh" >> /system/etc/passwd - András Korn
@András Korn 直到最近,Android 根本不使用那个文件。现在它声称是自动生成的,所以请注意更改可能不会生效。 - Evan Langlois
哦,好的,据我所知,在我的手机上已经包含了超级用户,因此不需要更改。 - András Korn

0

使用Termux在启动时自动启动,使用Macrodroid方法,并在后台保持运行的方法。我在已Root的设备上使用它,但我认为在任何未Root的设备上也应该可以使用:

  • 从Playstore安装Termux,或者对于旧的Android 5.x.x/6.x.x设备,安装最后一个可用版本termux-v0.79-offline-bootstraps.apk,例如从https://archive.org/download/termux-repositories-legacy/下载

  • 请注意,如果您使用的是旧的Android 5-6并使用termux-v0.79-offline-bootstraps.apk:您必须稍微调整一下存储库列表:

    $ 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 
    

    删除游戏和科学存储库

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

    更新(选择默认所有答案-按Enter键)

    $ pkg update
    
  • 为了让Termux在启动时启动,我使用Macrodroid:它可以在我曾经使用过的几乎所有旧或新的Android手机/平板电脑上运行。创建一个新的宏:触发器:(a)'设备启动',操作:(a)'启动Termux',(b)'等待10秒',(c)'启动主屏幕'。 (Macrodroid的屏幕截图)。检查它是否在重新启动时工作。现在应该启动Termux并放在后台。

  • 在我使用的版本termux-v0.79-offline-bootstraps.apk中,默认似乎安装了crond。尝试:$ crond,并使用$ pgrep crond检查守护程序crond是否正在运行。如果有问题,请在其他地方检查如何在Termux中安装crond。

  • 为了在Termux启动时执行crond,请在目录/data/data/com.termux/files/usr/etc/profile.d/中添加一个启动脚本(例如startup-crond)。此目录中的所有脚本都会在每次新登录时在bash的启动脚本中进行源代码处理。

    /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
    

    确保文件可执行:$ chmod 775 startup-crond

  • 这样,每次启动Termux时,.../usr/etc/profile.d/startup-crond都会检查crond是否正在运行,如果没有,则会启动守护程序。 "[OK]"消息确认一切正常。

  • 使用$ crontab -e在termux中添加您的crontab条目(使用vi编辑器)。这将在/data/data/com.termux/files/usr/var/spool/cron/crontabs/中创建一个带有Termux-App用户名的文件。 crontab的名称是Termux的用户名。您可以使用$ whoami进行确认。如果您不喜欢vi,也可以手动查看/编辑上述文件的内容。例如,使用nano。

  • 请注意,正如其他作者所提到的,这是用户级别的crontab,其语法为* * * * * my-script。与Linux的系统/etc/crontab不同,不要在my-script之

    与问题有些松散的联系,但在通过ssh工作时仍然很有趣:

    • 我更喜欢使用我的桌面键盘通过ssh在Termux上执行命令行操作,而不是在触摸屏上(如果有人感兴趣,这里是一个快速设置但不是最安全的摘要: $ pkg install openssh,用$ passwd创建密码,启动$ sshd,用$ ifconfig找到您的Android IP,在wlan0下查找条目:inet 192.168.XXX.XXX,从桌面登录到您的Android设备,使用$ ssh 192.168.XXX.XXX -p 8022)。当在Termux内部时,我还强烈建议使用Midnight-Commander浏览目录:$ pkg install mc
    • 以上方法的副作用:每次通过ssh登录Termux时,都会再次启动.../usr/etc/profile.d/startup-crond,并提醒crond正在运行。就我个人而言,这并不会打扰我。

0

我将把这个留在这里,供需要非root设备的人使用。

在继续之前,请注意:

  • 此方法将使用Termux应用程序,该应用程序需要在后台持续运行以执行cron

安装Termux Android应用程序,其说明可在其GitHub page上找到。

安装Termux后,按照从Reddit thread获取的步骤进行操作:

  • pkg install cronie termux-services(此步骤后重新启动termux)
  • sv-enable crond

运行crontab -e(就像在Linux机器上通常做的那样),然后添加您的cron。


0

这个应用程序运行得非常好:

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

cron格式是“用户”格式而不是“系统”格式,所有用户都以root身份运行。

这是我如何每天重新启动我的LineageOS 18.1 Android安装:

# 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接