2010-07-09 79 views
21

沒有多少運氣谷歌搜索這個問題,我想過把它張貼在SF上,但它實際上似乎是一個發展問題。如果沒有,請隨時遷移。bash腳本可以告訴它是否正在通過cron運行?

所以,我有一個腳本,每天凌晨3點左右通過cron運行。我也有時會手動運行相同的腳本。問題是,我每次手動運行我的腳本並失敗時,它會向我發送一封電子郵件;即使我可以查看輸出並在控制檯中查看錯誤。

有沒有一種方法讓bash腳本知道它是通過cron運行的(也許通過使用whoami)並且只發送電子郵件,如果是的話?我很樂意在我進行測試時停止接收電子郵件...

+1

你是否在腳本中發送電子郵件?默認情況下不會cron郵件輸出到crontab的所有者? – Cascabel 2010-07-09 17:13:05

+0

我是從內部發送電子郵件的,但我需要發送輸出。我沒有意識到cron做到了這一點。 – 2010-07-09 19:02:03

+0

嗨使用實際的傳出電子郵件,如'郵件',而不僅僅是使用unix郵件系統。 – gbtimmon 2014-10-17 15:03:58

回答

23

您可以嘗試「tty」以查看它是否由終端運行。它不會告訴你它是由cron專門運行的,但是你可以告訴它它是否「不是用戶作爲提示」。

你也可以得到你的父母的pid,然後在樹上尋找cron,雖然這有點笨重。

+13

感謝您的回答!我選擇的前一個答案實際上並不是我想要的(交互式shell)。由於你的回答,我通過谷歌搜索「bash tty test」找到了我真正需要的東西。基本上,在你的腳本中調用'tty -s',然後檢查'$?':如果它是0,你在tty中,如果它大於0,你就不是。 – 2010-08-03 15:52:30

+1

'tty'是一個外部命令(授予coreutils的一部分,但仍然是一個分支),有幾種方法可以使用內置的東西來執行相同的描述:https://unix.stackexchange.com/a/46801/103306 – 2017-11-24 10:15:34

9

爲什麼不具有-t用於測試的命令行參數或-c for cron。

或者更好的是:

[email protected]

如果不是指定,不發送電子郵件。

+0

我將腳本放在/etc/cron.daily中,因此我不能輕易添加參數,但我想我可以將它移動到真正的crontab中。我只是希望不必在命令行上添加參數或設置環境變量......雖然:在我的.bashrc文件中設置一個TESTING環境變量可以解決問題。 感謝您的建議。 – 2010-07-09 18:59:30

+0

將myscript.sh arg1 arg2 arg3放在/etc/cron.daily的腳本文件中沒有問題。我通常不會將我的腳本/二進制文件直接放入/etc/cron.*目錄中。我通常會將它留給執行cron作業的腳本(可能是另一個腳本)。然後我可以在其他環境中編寫我的腳本更通用並且可用。 – 2010-07-12 00:51:35

8

這兒有你兩種不同的選擇:

  • 就拿電子郵件發出你的腳本/程序的,讓cron的處理。如果您在crontab中設置了MAILTO變量,cron會發送任何打印到該電子郵件地址的內容。例如:

    [email protected] 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    
  • 設置在crontab的環境變量,用於確定是否在cron下運行。例如:

    THIS_IS_CRON=1 
    # run five minutes after midnight, every day 
    5 0 * * *  $HOME/bin/daily.job 
    

    ,並在你的腳本類似

    if [ -n "$THIS_IS_CRON" ]; then echo "I'm running in cron"; else echo "I'm not running in cron"; fi 
    
6

我知道這個問題是舊的,但我只是碰到了同樣的問題來了。這是我的解決方案:

CRON=$(pstree -s $$ | grep -q cron && echo true || echo false) 

然後用

if $CRON 
then 
    echo "Being run by cron" 
else 
    echo "Not being run by cron" 
fi 

同樣的想法作爲@eruciform提到的測試 - 跟隨您的PID這一進程樹檢查的cron。

注意:該解決方案僅適用於cron,與其他一些解決方案不同,該解決方案可在非交互式運行腳本時使用。

+0

我喜歡將var設置爲true或false(命令)的簡單性,這樣,如果$ CRON可以工作(相對於通常情況下的[「$ CRON」]),但請注意,如果$ CRON由於某種原因最終未定義,給定的版本評估爲true。不好。 – 2015-09-19 07:44:03

+0

我也很喜歡這個想法,但也看到有未定義的回報的風險。我結束了一個稍微修改後的版本,這在我看來似乎工作得非常流暢: CRON =「$(pstree -s $$ | grep -c cron)」 因此,您可以檢查$ CRON是否爲1或0. – frank42 2017-11-23 10:26:23

4

對我而言,有效的方法是檢查$TERM。在cron下它是「愚蠢的」,但在shell下是另一回事。在終端使用set命令,然後在cron腳本,並檢查了

if [ "dumb" == "$TERM" ] 
then 
    echo "cron" 
else 
    echo "term" 
fi 
+1

我還會檢查$ TERM是否爲空。 '[-n「$ TERM」-a「$ TERM」==「dumb」] && echo「interactive」||回聲「cron或沒有tty」' – Andor 2017-01-06 11:22:16

6

我有一個類似的問題。我解決了它,檢查標準輸出是否是TTY。這是一個檢查,看看是否腳本交互模式運行:

if [ -t 1 ] ; then 
    echo "interacive mode"; 
else 
    #send mail 
fi 

我得到這個來自:How to detect if my shell script is running through a pipe?

的-t測試返回true,如果文件描述符是開放的,指的是終端。 '1'是stdout。

4

我想建議一個新的答案,這個高度投票的問題。這隻適用於loginctl(例如Ubuntu 14.10+,RHEL/CentOS 7+)的systemd系統,但能夠提供比以前提出的解決方案更權威的答案。

service=$(loginctl --property=Service show-session $(</proc/self/sessionid)) 
if [[ ${service#*=} == 'crond' ]]; then 
    echo "running in cron" 
fi 

總結:用systemd,crond(如sshd等)創建一個新的session使用時,當它開始爲用戶的作業。此會話具有唯一用於整個機器正常運行時間的ID。每個會話都有一些屬性,其中一個是啓動它的服務的名稱。 loginctl可以告訴我們這個屬性,這將是「crond當且僅當會話實際上是由crond的啓動值。


優勢超過使用環境變量:

  • 無需修改的cron條目添加特殊的調用或環境變量
  • 一箇中間過程修改環境變量沒有可能創建一個假陽性或假陰性

優於tty的測試:

  • 在管道,啓動腳本沒有誤報等

優勢在檢查進程樹:

  • 自謂也有crond在他們的名字
  • 沒有進程沒有誤報如果假陰性腳本六親不認
0

我也喜歡來自Tal的想法,同時也看到了不確定回報的風險。我結束了一個稍微修改後的版本,這似乎在我看來,工作的非常流暢:

CRON="$(pstree -s $$ | grep -c cron)"

所以,你可以檢查$科雷隨時爲1或0。

相關問題