2013-04-03 47 views
1

有沒有辦法終止一個shell函數非交互式而不會殺死運行它的shell?非交互式地終止一個shell函數

我知道shell可以被告知如何響應信號(例如USR1),但我無法弄清楚信號處理程序如何終止函數。

如果需要,您可能會認爲要終止的函數是以「可終止」的方式寫入的(即通過聲明一些合適的選項)。

(我的切身利益是如何做到這一點爲zsh,但我也想知道如何做到這一點的bash/bin/sh

編輯:在回答羅布瓦特的建議:

% donothing() { echo $$; sleep 1000000 } 
% donothing 
47139 

如果在這一點上,我在運行外殼相同的終端打Ctrl-C,則函數donothing確實終止,而我得到的命令提示符後面。但如果相反,從不同的shell會話,我跑

% kill -s INT 47139 

...的donothing功能確實終止。

+1

你的意思是像控制c的東西? –

+0

谷歌例如「bash信號處理」和第一匹配描述使用'trap'的很多示例的bash-shell的信號處理。 –

+0

@RobWatts:我編輯了我的帖子以說明你的建議。 – kjo

回答

1

也許我不完全明白你想要什麼,但也許這樣?

trap "stopme=1" 2 

function longcycle() { 
    last=$1 
    for i in 1 2 3 4 5 
    do 
     [ ! -z "$stopme" ] && return 
     echo $i 
     sleep 1 
    done 
} 

stopme="" 
echo "Start 1st cycle" 
longcycle 
echo "1st cycle end" 

echo "2nd cycle" 
stopme="" 
longcycle 
echo "2nd cycle end" 

以上是針對bash的。運行它,然後嘗試按CTRL-C。

或爲not interactively,保存以上,例如my_command,然後嘗試:

$ ./my_command & #into background 
$ kill -2 $! #send CTRL-C to the bg process 

編輯:

解決方案,用於在bash你sleep例如:

$ donothing() { trap '[[ $mypid ]] && trap - 2 && kill $mypid' 0 2; sleep 1000000 & mypid=$!;wait; } 
$ donothing 

當你從另一個終端發送信號將終止它。記住,信號'0'是正常結束的過程。語義名稱:0 = EXIT,2 = INT ...等等

並記住,信號也發送到到進程不是功能。在你的例子中,進程是當前(交互式shell),所以必須使用等待技巧來獲得可中斷的...不是一個好的解決方案 - 但是當想要中斷某些在交互式shell中運行的東西時唯一的方法(不是一個叉)從另一個終端...

+0

爲什麼我不能在合適的'kill'命令中複製在原始終端上按下'Ctrl-C'的效果? – kjo

+0

因爲信號如何工作。殼牌有特殊的信號處理。當你運行一個命令時,shell會自行分叉並恢復默認的信號處理,例如,當您將SIGINT發送到分叉進程時,進程將終止。但是當你直接在你的終端外殼上運行一個shell函數(而不是分叉函數)時 - 外殼具有特殊的信號處理功能,例如,當你在鍵盤上按下CTRL-C時,它會捕捉它並以它自己的方式處理它。 – jm666

+0

檢查我的答案另一個問題:http://stackoverflow.com/questions/6108953/how-does-ctrl-c-terminate-a-child-process/6109189#6109189 – jm666