2013-10-17 12 views
0

我有一個在後臺運行的腳本。它打開到服務器的SSH連接並無限期地尾隨文件。當我讓我的Mac進入睡眠狀態時,SSH連接關閉。這是有問題的腳本:在ZSH/OS X中只運行在後臺運行的腳本的一個實例

#!/bin/sh 

(ssh <user>@<ip> -o PermitLocalCommand=no \ 
": > .irssi/fnotify ; tail -f .irssi/fnotify " | \ 
while read heading message; do     \ 
growlnotify -s -t "${heading}" -m "${message}"; \ 
done)& 

在這一點上,我不得不跑ps aux | grep ssh,找到合適的工藝和手工殺死它;這很乏味。所以,我有幾個問題和可能的答案:

  1. 有沒有辦法重命名腳本的進程名,這樣我可以通過名字,每次我再次運行它殺了它?
  2. 否則,當我執行它時,是否存在腳本的pid,然後在我再次運行時將其殺死?

第一個解決方案是不可能的我相信,但它值得問。

對於第二個方案,我做了一些研究,我去的地方,但還不夠遠......這是我有:

我設法拿到劇本本身的pid特定的不是一個SSH連接。但從我所看到的腳本的pid始終是<pid of ssh connection> - 1

所以我需要在腳本的pid中加1,但我無法做到這一點。但無論如何, 是一個可行的解決方案?

否則,請問有哪些替代解決方案?

+0

我不知道,但使用'-o ServerAliveInterval = 0'可以保持連接,只要客戶端過程亦不是被殺。 – chepner

回答

1

你不需要做任何PID跟蹤,讓shell在一個循環中處理ssh斷開連接。

#!/bin/sh 
while true ; do 
    ssh -o BatchMode=yes [email protected] ' 
     : > ~/.irssi/notify 
     tail -f ~/.irssi/notify 
    ' | while read -r title message ; do 
     growlnotify -s -t "$title" -m "$message" 
    done 
    sleep 5 # retry timeout 
done 

調整[email protected],然後重試超時的味道,保存在你的路徑,使用chmod + X吧,就像從xinitrc/xsession或在任期中背景,如果你想看輸出,方便的時候運行。

爲了防止出現多個事件,您可以添加如下內容。

if [ -e /tmp/sshnotify.pid ] ; then 
    read pid < /tmp/sshnotify.pid 
    if kill -0 $pid > /dev/null 2>&1 ; then 
     echo >&2 already running 
     exit 1 
    fi 
fi 
echo $$ > /tmp/sshnotify.pid 
+0

我的解決方案有兩個問題:1.我不適合每X秒執行多次SSH連接。 2.我試圖在腳本的頂部添加'echo $$',並且它返回了錯誤的pid。 –

+0

1.它沒有;沒有背景。腳本等待'ssh'終止,它會丟失連接,_then_等待X秒後再嘗試重新連接'ssh',直到整個腳本在系統關閉時被終止或手動使用'kill $(cat/tmp /sshnotify.pid)'或'pkill '。 2.'$$'不會返回錯誤的pid,它會返回運行此腳本的shell的pid。你不需要任何其他的東西,因爲如果腳本被殺死的話,子過程也是如此。 'echo $$> file'就是這樣,我們有一個文件位於已知位置,其中包含已經運行的腳本的pid。 – peth

+0

感謝您的澄清。我會接受你的回答。 –

0

由於您使用的是zsh,因此您可以通過設置參數ARGV0來設置ssh進程的名稱。你可以在ssh之前加ARGV0=WhateverNameYouWant,但仍然在括號內。

在後臺運行的最後一個進程的PID可用爲$!,但是由於您沒有一個簡單的命令,因此您將不會是ssh進程的PID。但是,我懷疑這可能是你用來找到腳本的PID。

你可以通過將其包裝在$(())內,如$(($! + 1))那樣在殼體中進行數學運算。您可以將$關閉這些表達式中的某些變量引用,但這似乎不適用於$!。但是,將PID加1不是獲得子進程的PID的可靠方法;只是在錯誤的時間裏產生一個孩子纔會拋出一個不同的過程。

+0

因此設置過程的名稱是最好的解決方案?我想到的是將流程的名稱導出到一個變量中,然後檢查該流程,並在流程運行時終止該流程。但是,如何檢查指定的進程是否正在運行? :S –