Mac創建定時任務

Mac 有兩種方式可以添加定時任務:

  • crontab 命令
  • launchctl 定時任務

crontab 命令

通過crontab 命令,我們可以在固定的間隔時間執行指定的系統指令或 shell script腳本。時間間隔的單位可以是分鐘、小時、日、月、周及以上的任意組合。這個命令非常適合週期性的日誌分析或數據備份等工作。

命令格式

crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]
  • -u user:用來設定某個用戶的crontab服務;
  • file:file是命令文件的名字,表示將file做爲crontab的任務列表文件並載入crontab。如果在命令行中沒有指定這個文件,crontab命令將接受標準輸入(鍵盤)上鍵入的命令,並將它們載入crontab。
  • -e:編輯某個用戶的crontab文件內容。如果不指定用戶,則表示編輯當前用戶的crontab文件。
  • -l:顯示某個用戶的crontab文件內容,如果不指定用戶,則表示顯示當前用戶的crontab文件內容。
  • -r:從/var/spool/cron目錄中刪除某個用戶的crontab文件,如果不指定用戶,則默認刪除當前用戶的crontab文件。
  • -i:在刪除用戶的crontab文件時給確認提示。

crontab 文件格式

分 時 日 月 星期 要運行的命令
  • 第1列分鐘1~59
  • 第2列小時1~23(0表示子夜)
  • 第3列日1~31
  • 第4列月1~12
  • 第5列星期0~7(0和7表示星期天)
  • 第6列要運行的命令

備份/恢復 crontab

可以定時備份 crontab 以防誤刪操作

# 備份
crontab -l > $HOME/.mycron
# 恢復
crontab $HOME/.mycron

定時實例

# 每1分鐘執行一次myCommand
* * * * * myCommand

# 每小時的第3和第15分鐘執行
3,15 * * * * myCommand

# 在上午8點到11點的第3和第15分鐘執行
3,15 8-11 * * * myCommand

# 每隔兩天的上午8點到11點的第3和第15分鐘執行
3,15 8-11 */2  *  * myCommand

# 每週一上午8點到11點的第3和第15分鐘執行
3,15 8-11 * * 1 myCommand

# 晚上11點到早上7點之間,每隔一小時重啓smb
* 23-7/1 * * * /etc/init.d/smb restart

注意清理系統用戶的郵件日誌

每條任務調度執行完畢,系統都會將任務輸出信息通過電子郵件的形式發送給當前系統用戶,這樣日積月累,日誌信息會非常大,可能會影響系統的正常運行,因此,將每條任務進行重定向處理非常重要。 例如,可以在crontab文件中設置如下形式,忽略日誌輸出:

0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

launchctl 定時任務

下面將手把手教你在mac上創建定時任務。(任務目標:每天晚上十點定時執行/Users/demo/helloworld.py的python程序)

1. 創建run.sh腳本

進入 helloworld.py程序所在目錄
cd /User/demo
創建run.sh腳本
vi run.sh
添加執行helloworld.py的命令

#!/bin/sh

# 記錄一下開始時間
echo `date` >> /Users/demo/log &&
# 進入helloworld.py程序所在目錄
cd /Users/demo &&
# 執行python腳本(注意前面要指定python運行環境/usr/bin/python,根據自己的情況改變)
/usr/bin/python helloworld.py
# 運行完成
echo 'finish' >> /Users/demo/log

:wq保存退出

注意,腳本要改成可執行的權限
chmod 777 run.sh

2. 編寫plist文件

launchctl 將根據plist文件的信息來啓動任務。
plist腳本一般存放在以下目錄:

  • /Library/LaunchDaemons -->只要系統啓動了,哪怕用戶不登陸系統也會被執行

  • /Library/LaunchAgents -->當用戶登陸系統後纔會被執行

更多的plist存放目錄:

~/Library/LaunchAgents :由用戶自己定義的任務項
/Library/LaunchAgents :由管理員爲用戶定義的任務項
/Library/LaunchDaemons :由管理員定義的守護進程任務項
/System/Library/LaunchAgents :由Mac OS X爲用戶定義的任務項
/System/Library/LaunchDaemons :由Mac OS X定義的守護進程任務項

進入~/Library/LaunchAgents,創建一個plist文件com.demo.plist

 

<?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>
  <!-- Label唯一的標識 -->
  <key>Label</key>
  <string>com.demo.plist</string>
  <!-- 指定要運行的腳本 -->
  <key>ProgramArguments</key>
  <array>
    <string>/Users/demo/run.sh</string>
  </array>
  <!-- 指定要運行的時間 -->
  <key>StartCalendarInterval</key>
  <dict>
        <key>Minute</key>
        <integer>00</integer>
        <key>Hour</key>
        <integer>22</integer>
  </dict>
<!-- 標準輸出文件 -->
<key>StandardOutPath</key>
<string>/Users/demo/run.log</string>
<!-- 標準錯誤輸出文件,錯誤日誌 -->
<key>StandardErrorPath</key>
<string>/Users/demo/run.err</string>
</dict>
</plist>

launchctl 通過配置文件指定執行週期和任務,不同於 crontab,launchctl 的最小時間間隔是 1s。

plist 文件存放路徑爲/Library/LaunchAgents/Library/LaunchDaemons,前者僅當用戶登陸後才被執行,後者只要系統啓動就會被執行。

支持兩種方式配置執行時間:

  • StartInterval: 指定腳本每間隔多長時間(單位:秒)執行一次;

  • StartCalendarInterval: 可以指定腳本在多少分鐘、小時、天、星期幾、月時間上執行,類似如crontab的中的設置,包含下面的 key:

    Minute <integer>
    The minute on which this job will be run.
    
    Hour <integer>
    The hour on which this job will be run.
    
    Day <integer>
    The day on which this job will be run.
    
    Weekday <integer>
    The weekday on which this job will be run (0 and 7 are Sunday).
    
    Month <integer>
    The month on which this job will be run.

    3. 加載命令

    launchctl load -w com.demo.plist
    這樣任務就加載成功了。

  • # 加載任務, -w選項會將plist文件中無效的key覆蓋掉,建議加上
    $ launchctl load -w com.demo.plist
    
    # 刪除任務
    $ launchctl unload -w com.demo.plist
    
    # 查看任務列表, 使用 grep '任務部分名字' 過濾
    $ launchctl list | grep 'com.demo'
    
    # 開始任務
    $ launchctl start  com.demo.plist
    
    # 結束任務
    $ launchctl stop   com.demo.plist
    

    plist 文件的字段說明

  • <?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.uniflor.notifier</string>
    
        <!-- 要運行的程序, 如果省略這個選項,會把ProgramArguments的第一個
        元素作爲要運行的程序 -->
        <key>Program</key>
        <string>/Users/uniflor/script.sh</string>
    
        <!-- 命令, 第一個爲命令,其它爲參數-->
        <key>ProgramArguments</key>
        <array>
          <string>/Users/uniflor/script.sh</string>
        </array>
    
        <!-- 運行時間 -->
        <key>StartCalendarInterval</key>
        <dict>
    
          <key>Minute</key>
          <integer>30</integer>
    
          <key>Hour</key>
          <integer>9</integer>
    
          <key>Day</key>
          <integer>1</integer>
    
          <key>Month</key>
          <integer>5</integer>
    
          <!-- 0和7都指星期天 -->
          <key>Weekday</key>
          <integer>0</integer>
    
        </dict>
    
        <!-- 運行間隔,與StartCalenderInterval使用其一,單位爲秒 -->
        <key>StartInterval</key>
        <integer>30</integer>
    
        <!-- 標準輸入文件 -->
        <key>StandardInPath</key>
        <string>/Users/uniflor/run-in.log</string>
    
        <!-- 標準輸出文件 -->
        <key>StandardOutPath</key>
        <string>/Users/uniflor/Bin/run-out.log</string>
    
        <!-- 標準錯誤輸出文件 -->
        <key>StandardErrorPath</key>
        <string>/Users/uniflor/Bin/run-err.log</string>
    
      </dict>  
    </plist>
    

     

配置文件

進入到~/Library/LaunchAgents下建一個plist文件com.test.launchctl.plist,內容如下:

<?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.test.launchctl.plist</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python</string>
        <string>/Workspace/test.py</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Minute</key>
        <integer>4</integer>
        <key>Hour</key>
        <integer>13</integer>
    </dict>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/AutoMakeLog.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/AutoMakeLog.err</string>
</dict>
</plist>
  • StartCalendarInterval: 執行週期
  • RunAtLoad: 加載時執行一次
  • StandardOutPath: 標準輸出路徑
  • StandardErrorPath: 錯誤輸出路徑

管理定時任務

  • 加載任務
cd ~/Library/LaunchAgents
launchctl load com.test.launchctl.plist
  • 卸載任務
launchctl unload com.felink.gitmirror.plist
  • 立即執行一次任務
launchctl start ccom.test.launchctl.plist
  • 停止任務
launchctl stop ccom.test.launchctl.plist

 

寫個簡單的applescript。

on callmeican()

    set meican_url to "https://meican.com" as string

    tell application "Google Chrome"

        open location meican_url

        activate

    end tell

end callmeican


say "不要這麼拼了,預訂美餐時間到了"


display dialog "不要這麼拼了,預訂美餐時間到了(截至時間16:30)!" buttons {"好的", "我不定了"} default button 1


if the button returned of the result is "好的" then

    -- action for 1st button goes here

    callmeican()

end if

腳本的作用大概是MAC會通過彈窗和語音提醒我該訂餐了,如果選擇定,就自動用瀏覽器打開訂餐的頁面。這個腳本每天在四點執行。

1、使用crontab設置定時任務

crontab -e 或者sudo crontab -e。

00 16 * * * osascript /Users/hanlingzhi/project/applescript/meican.scpt

輸入完成後,保存退出。系統自動建立新cron,提示如下:crontab: installing new crontab。設置非常簡單。

2、使用蘋果的Schedule jobs using launchd設置定時任務。需要寫一個plist文件,描述任務的動作、間隔的時間、日誌輸出等參數。

我創建一個plist文件com.hanlingzhi.cron.meican.plist,大概內容如下:

<?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.hanlingzhi.cron.meican</string>

    <!-- 命令, 第一個爲命令,其它爲參數-->

    <key>ProgramArguments</key>

    <array>

        <string>osascript</string>

      <string>/Users/hanlingzhi/project/applescript/meican.scpt</string>

    </array>

    <!-- 運行時間 -->

    <key>StartCalendarInterval</key>

    <dict>

      <key>Minute</key>

      <integer>0</integer>

      <key>Hour</key>

      <integer>16</integer>

    </dict>

    <!-- 標準輸入文件 -->

    <key>StandardInPath</key>

    <string>/Users/hanlingzhi/project/applescript/log/run-in-meican.log</string>

    <!-- 標準輸出文件 -->

    <key>StandardOutPath</key>

    <string>/Users/hanlingzhi/project/applescript/log/run-out-meican.log</string>

    <!-- 標準錯誤輸出文件 -->

    <key>StandardErrorPath</key>

    <string>/Users/hanlingzhi/project/applescript/log/run-err-meican.log</string>

  </dict>

</plist>

然後將plist文件放在/Users/hanlingzhi/Library/LaunchAgents,你的用戶目錄下,然後執行launchctl load plist就可以啓動了。

plist腳本存放路徑爲/Library/LaunchDaemons或用戶目錄/Library/LaunchAgents,其區別是後一個路徑的腳本當用戶登陸系統後纔會被執行,前一個只要系統啓動了,哪怕用戶不登陸系統也會被執行。

可以通過兩種方式來設置腳本的執行時間。一個是使用StartInterval,它指定腳本每間隔多長時間(單位:秒)執行一次;另外一個使用StartCalendarInterval,它可以指定腳本在多少分鐘、小時、天、星期幾、月時間上執行,類似如crontab的中的設置。

<key>StartInterval</key>

<integer>3600</integer>

或者

<key>StartCalendarInterval</key>

<dict>

  <key>Minute</key>

  <integer>30</integer>

  <key>Hour</key>

  <integer>9</integer>

</dict>

launchctl的命令使用大家看一下幫助文檔。

由於操作還是比較複雜,爲了幫助快速執行,寫了個shell快速拷貝新的plist並完成服務重啓

__path='/Users/hanlingzhi/project/applescript'

__plist_path=${__path}/plist

__launchagents_path='/Users/hanlingzhi/Library/LaunchAgents'

# 拷貝plist到用戶自己定義的任務項目錄

cp -rf ${__plist_path}/* ${__launchagents_path}

# 根據plist中的文件遍歷load

for plist_file in `ls ${__plist_path}`

do

    echo "重啓${plist_file}定時任務"

    launchctl unload ${__launchagents_path}/${plist_file}

    sleep 0.5

    launchctl load ${__launchagents_path}/${plist_file}

    task_name=`echo ${plist_file} | sed 's/.plist//g'`

    launchctl list | grep ${task_name}

done

 


總結一下

雖然plist的設置會複雜很多。但是當前在mac os還是傾向於推薦使用Plist的方法,crontab已不推薦使用。

兩者的區別:

1、plist可以設置到秒,而crontab只能到分鐘。

2、plist可以同時應用於Mac OS/Iphone。

3、plist對於MAC上系統交互的操作更支持(我就出現過用crontab設置,運行時出現execution error: 不允許用戶交互。 (-1713)的錯誤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章