bash 在没有 root 权限的情况下,在 Mac OS X 上定期运行 shell 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23872734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:32:16  来源:igfitidea点击:

Run a shell script periodically on Mac OS X without root permission

macosbashcronstartuplaunchd

提问by user3671325

I want to start up a file with .sh type or .py on mac os x without using root , I searched in google and found launchctl can help me ,

我想在不使用 root 的情况下在 mac os x 上启动一个 .sh 类型或 .py 的文件,我在谷歌搜索,发现 launchctl 可以帮助我,

so i read tutorial and do same in tutorial but it not work for me , [i using mac os x 10.9 x64]

所以我阅读教程并在教程中做同样的事情,但它对我不起作用,[我使用 mac os x 10.9 x64]

My .plist file [run 1.sh file in every 60second] :

我的 .plist 文件 [每 60 秒运行 1.sh 文件]:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.alvin.crontabtest</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/paul/Desktop/1.sh</string>
  </array>
  <key>Nice</key>
  <integer>1</integer>
  <key>StartInterval</key>
  <integer>60</integer>
  <key>RunAtLoad</key>
  <true/>
  <key>StandardErrorPath</key>
  <string>/tmp/AlTest1.err</string>
  <key>StandardOutPath</key>
  <string>/tmp/AlTest1.out</string>
</dict>
</plist>

source of 1.sh:

1.sh的来源:

echo '+' >> /Users/paul/Desktop/worked.txt

I put Run.plist in /Users/paul/Run.plist

我把 Run.plist 放在 /Users/paul/Run.plist

and run command from terminal :

并从终端运行命令:

launchctl load /Users/paul/Run.plist
Launchctl start com.alvin.crontabtest

commands execute without any error but i not see anything in worked.txt

命令执行时没有任何错误,但我在 work.txt 中没有看到任何内容

can anyone help me please ?

有人可以帮我吗?

采纳答案by ghoti

Any particular reason you don't want to use a normal crontab?

您不想使用普通 crontab 的任何特殊原因?

% echo "* * * * * /Users/paul/Desktop/1.sh" | crontab -

This command should add a cron job that runs once per minute.

此命令应添加一个每分钟运行一次的 cron 作业。

NOTE that this command will also replace any crontab that you already have.The crontab -command should be used with caution, as a short-cut.

请注意,此命令还将替换您已有的任何 crontab。crontab -命令应谨慎使用,作为捷径。

If you want to edit an existing crontab, so as to avoid obliterating previously set jobs, you can use crontab -e. (If it launches vimand you don't know how to use vim, you can exit by hitting ESC:q!Enterand then go find editor documentation.)

如果要编辑现有的 crontab,以避免删除之前设置的作业,可以使用crontab -e. (如果它启动vim并且您不知道如何使用vim,您可以通过点击退出ESC:q!Enter然后去查找编辑器文档。)

If you want instructions on how to edit crontabs, type man crontabat your shell. If you want syntax information on the crontab file, man 5 crontabwill show you that.

如果您需要有关如何编辑 crontab 的说明,请man crontab在您的 shell 中键入。如果您想要有关 crontab 文件的语法信息,man 5 crontab将显示给您。

Enjoy!

享受!



UPDATE:(per comments)

更新:(根据评论)

To run your job every 30 seconds requires a simple hack. Cron only runs jobs on a per minute basis, so to run things every 30 seconds, you can have two jobs, one of which has a 30 second delay. For example:

每 30 秒运行一次你的工作需要一个简单的技巧。Cron 仅以每分钟为基础运行作业,因此要每 30 秒运行一次,您可以有两个作业,其中一个有 30 秒的延迟。例如:

  #Mn Hr Da Mo DW Command
  *   *  *  *  *   /Users/paul/Desktop/1.sh
  *   *  *  *  *   sleep 30; /Users/paul/Desktop/1.sh

Hope this helps.

希望这可以帮助。

回答by mklement0

To clarify: The OP's .plistfile itselfwas perfectly OK- the problem turned out to be insidethe shell script invoked (not shown in the question).

澄清一下:OP 的.plist文件本身完全没问题 - 问题出调用的 shell 脚本内部(问题中未显示)。

On OS X, using .plistfiles loaded by CLI launchctland invoked by daemon manager launchdis the preferredway of scheduling (recurring) tasks(see below for more).

在 OS X 上,使用.plist由 CLI 加载并由launchctl守护程序管理器调用的文件launchd是调度(重复)任务的首选方式(更多信息见下文)。

Things to note:

注意事项:

  • The format of launchd.plistfilesis described in man launchd.plist
  • For a .plistfile to be loaded every time the currentuser logs in, it must be placed in ~/Library/LaunchAgents/(all-usersfiles must be placed in /Library/LaunchAgent/- requires root privileges).
  • Specifying output-capture fileswith keys StandardOutPathand StandardErrorPathmeans that successive invocations appendto the files specified, which means that these files keep growing indefinitely, unless managed externally.
  • Re troubleshooting: @Grady Player's advice applies: launch Console.appand look for com.apple.launchd.peruserentries - a failure to invoke the command specified in the .plistwould show there.
  • 格式launchd.plist的文件中描述man launchd.plist
  • 对于.plist每次当前用户登录时要加载的文件,必须将其放入~/Library/LaunchAgents/(必须放入所有用户文件/Library/LaunchAgent/- 需要 root 权限)。
  • 指定输出捕获文件的钥匙StandardOutPath,并StandardErrorPath意味着后续调用追加到指定的文件,这意味着这些文件保持无限增长,除非外部管理
  • 重新故障排除:@Grady Player 的建议适用:启动Console.app并查找com.apple.launchd.peruser条目 - 调用中指定的命令失败.plist将显示在那里。


@ghoti's answerdescribes a general Unix alternativeto launchd, cron(typically used on Linux):

@ ghoti的答案描述了一般的Unix的替代launchdcron(通常在Linux上使用):

As for how cronrelates to OS X: @ghoti asks:

至于cron与 OS X 的关系:@goti 问:

Any particular reason you don't want to use a normal crontab?

您不想使用普通 crontab 的任何特殊原因?

On OS X, man crontabadvises (emphasis added):

在 OS X 上,man crontab建议(强调):

Although cron(8) and crontab(5) are officially supported under Darwin [OS X], their functionality has been absorbed into launchd(8), which provides a more flexible way of automatically executing commands. See launchctl(1) for more information.

尽管达尔文 [OS X] 正式支持 cron(8) 和 crontab(5),但它们的功能已被吸收到 launchd(8) 中,它提供了一种更灵活的自动执行命令的方式。有关详细信息,请参阅 launchctl(1)。

The bottom lineis this:

底线是这样的:

  • If you come from a *nix background, you may be more comfortable with continuing to use cronand crontab, assuming:
    • you're aware of the fact that additional background tasks, scheduled via launchd, may exist.
    • you're aware of cron's limitations and can work with/around them.
  • 如果您来自 *nix 背景,您可能更愿意继续使用cronand crontab,假设:
    • 您知道launchd可能存在通过 安排的其他后台任务。
    • 您知道cron的限制并且可以使用/解决它们。
  • Otherwise, on OS X:
    • many third-party apps use the native launchdfeature and thus specify periodic background tasks via .plistfiles in /Library/LaunchAgents(for all users) or ~/Library/LaunchAgents(for the current user).
    • If you want to centralize management of background tasks to these locations and/or you want to take advantage of the increased flexibility that launchdprovides, go with specifying background tasks via .plistfiles evaluated by launchd.
  • 否则,在 OS X 上
    • 许多第三方应用程序使用本机launchd功能,因此通过(对于所有用户)或(对于当前用户)中的.plist文件指定定期后台任务。/Library/LaunchAgents~/Library/LaunchAgents
    • 如果你想集中的后台任务管理,这些位置和/或要采取的增加灵活性的优势launchd提供,请通过指定后台任务.plist的评估文件launchd

Adding simplecrontasks is probably simpler than creating .plistfiles for launchd, but 3rd-party utilities such as Lingon 3can help with the latter.

添加简单cron任务可能比为 创建.plist文件更简单launchd,但 3rd-party 实用程序(例如Lingon 3)可以帮助后者。

Also, there are subtle differencesin how crontasks are invoked vs. per-user launchdtasks: for instance, the former do not allow user interaction via AppleScript, whereas the latter do.

另外,还有一些细微的差别如何cron任务调用与每个用户的launchd任务:比如,前者不允许通过AppleScript的用户交互,而后者做的。



Case in point re increased flexibility of launchd: the OP, in a follow-up comment, asks for the task to run every 30seconds:

launchd举个例子,增加了灵活性:OP,在后续评论中,要求任务每30秒运行一次:

  • The minimum interval for crontasks is 60 seconds, necessitating the workaround in @ghoti's answer.

  • By contrast, with the launchd.plistfile, changing <key>StartInterval</key><integer>60</integer>to <key>StartInterval</key><integer>30</integer>is enough.

  • 任务最小间隔为cron60 秒,需要在@ghti 的回答中解决。

  • 相比之下,与launchd.plist文件,改变<key>StartInterval</key><integer>60</integer><key>StartInterval</key><integer>30</integer>就够了。