我找不到我的问题的答案:是否可以使用(或其他方式)运行crontab
以重新启动 Androidbusybox
尝试运行 crontab,它抱怨未知 uid 0。
试图运行重新启动,它什么也不做。
或者我现在要求的是不可能的事情?
要求
Root 访问权限:用于超级用户命令,如重启或 init.d 配置。Crond 仍然可以在普通用户权限下运行。
Busybox:用于“crond”服务
(可选)init.d 支持:在引导时启动“crond”服务。或者通过 Magisk post-fs-data.d 脚本开始。
创建 cronjob
在目录 /data/crontab/ 中创建 cronjob 文件(即使在 sdcard 中也可以是任何可访问的目录),文件名为“root”。将您的 cronjob 写入文件“root”中。
echo '
53 * * * * reboot' >> /data/crontab/root
无需重启即可测试
现在打开设备中的任何终端仿真器并运行以下命令..
su -
crond -b -c /data/crontab
现在 crond 服务将启动,检查类型pgrep -l crond
或ps | 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
示例 cronjobs
53 * * * * 重启
将在每小时的第 53 分钟重新启动您的设备。
注意: 1.如果修改了crontab,记得杀掉已有的crond守护进程后重启。
如果 crond 不遵守您的时区,您可能需要更新设备中的 tzdata。
最好用 */1 * * * * 进行测试,看看它是否有效。
这是对 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”。这似乎是在二进制文件中硬编码的。
接下来,我将以下行添加到我的初始化脚本中
/system/xbin/mount -o remount,rw /
/system/xbin/ln -s /system/bin/ /bin
/system/xbin/mount -o remount,ro /
就是这样。在那之后它工作得很好
如果您收到错误“只读文件系统”,则需要将 /system 重新挂载为读写:
mount -o rw,remount /dev/stl12 /system
完成后,将其重新安装为只读:
mount -o ro,remount /dev/stl12 /system
您可能需要设置您的 TimeZone 并添加一个 root 用户。添加root用户可以这样完成:
echo "root:x:0:0::/system/etc/crontabs:/system/bin/sh" > /system/etc/passwd
获得正确的 TimeZone 字符串很奇怪。将 TZ 环境变量设置为时区字符串,并确保 crond 得到它。我将它置于 GUI 环境的控制之下,并使用以下内容获取 TimeZone(可能不正确,因为我尚未在其他时区测试过它)。
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,那么您可能必须将您的 crontab 保存在 /system
请注意,cron 在 Android 下并不总是准时运行,因为它喜欢睡过头。