我有一個perl scipt,我需要它在Linux機器上每隔兩小時結束一次。我打算做一個單獨的腳本,並將其添加到cron.d來完成此操作,但我想要一個更簡單的方法。它必須做一個優雅的退出,因爲在做一個CTRL + C之後,它會寫入一個日誌文件並且殺死它不會寫入文件。每2小時自動退出perl腳本
回答
您可以通過在$SIG{INT}
設置子程序趕按Ctrl-C發送的信號:
$ perl -e '$SIG{INT} = sub { print "Caught signal, cleaning up\n"; exit 0 }; while(1) {}'
子內做你清理和你去那裏。
聽起來好像腳本已經捕獲到了SIGINT(因此它爲什麼會在Ctrl-C上寫入日誌)。問題是如何從外部殺死腳本。 –
@AndrewMedico - 不,我不認爲這是真的。這個問題說(強調增加)「它必須做一個優雅的退出,因爲在做一個CTRL + C之後,它會寫入一個日誌文件並且_killing它不會寫入file_。」這意味着我沒有信號處理程序。如果有的話,當信號被捕獲時關閉文件句柄或者(如果你想稍微馬虎一點)沖洗緩衝區就會很簡單。 – frezik
您可以設置在腳本的開始報警,併爲它提供一個處理程序:
alarm 60 * 60 * 2;
local $SIG{ALRM} = sub {
warn "Time over!\n";
# Do the logging here...
exit
};
的問題是,你如何會再次重新啓動腳本。
對於重新啓動腳本,我希望這是cron.d能夠做到的地方 – EnigmaRenegade
@EnigmaRenegade:您仍然應該驗證腳本是否過早結束或根本不會停止。 – choroba
有沒有一種方法可以製作單獨的腳本來做到這一點? – EnigmaRenegade
包裝保持簡單。
#!/usr/bin/perl
# usage:
# restarter program [arg [...]]
use strict;
use warnings;
use IPC::Open3 qw(open3);
use POSIX qw(WNOHANG);
use constant RESTART_AFTER => 2*60*60;
use constant KILL_INT_WAIT => 30;
use constant KILL_TERM_WAIT => 30;
use constant WAIT_POLL => 15;
sub start_it {
open(local *NULL, '<', '/dev/null')
or die($!);
return open3('<&NULL', '>&STDOUT', '>&STDERR', @_);
}
sub wait_for_it {
my ($pid, $max_wait) = @_;
my $end_time = time + $max_wait;
while (1) {
if (waitpid($pid, WNOHANG) > 0) {
return 1;
}
my $time = time;
if ($end_time >= $time) {
return 0;
}
sleep(1);
}
}
sub end_it {
my ($pid) = @_;
kill(INT => $pid)
or die($!);
return if wait_for_it($pid, KILL_INT_WAIT);
kill(TERM => $pid)
or die($!);
return if wait_for_it($pid, KILL_TERM_WAIT);
kill(KILL => $pid)
or die($!);
waitpid($pid, 0);
}
sub run_it {
my $end_time = time + RESTART_AFTER;
my $pid = start_it(@_);
while (1) {
if (waitpid($pid, WNOHANG) > 0) {
last;
}
my $time = time;
if ($end_time >= $time) {
end_it($pid);
last;
}
my $sleep_time = $end_time - $time;
$sleep_time = WAIT_POLL if $sleep_time > WAIT_POLL; # Workaround for race condition.
sleep($sleep_time);
}
my $status = $?;
if ($? & 0x7F) { warn("Child killed by signal ".($? & 0x7F)."\n"); }
elsif ($? >> 8) { warn("Child exited with error ".($? >> 8)."\n"); }
else { warn("Child exited with succcesfully.\n"); }
}
run_it(@ARGV) while 1;
您可能希望將發送到處理程序的信號轉發給子節點。
- 1. 如何退出perl腳本中的chroot?
- 2. 從bash腳本獲取perl腳本的輸出並退出
- 3. 退出perl函數而不退出腳本
- 4. 在腳本中運行gdb時自動退出
- 5. shell腳本退出
- 6. 退出PowerShell腳本
- 7. Strongloop自定義腳本不會退出
- 8. 如何讓bash在每次退出時執行腳本?
- 9. 我退出()腳本,但它不退出
- 10. 啓動時啓動perl腳本
- 11. Perl php腳本自動安裝?
- 12. Bash - 從子腳本退出父腳本
- 13. 「腳本」命令退出bash腳本
- 14. 從的bash shell腳本自動退出的錯誤
- 15. 退出從一個JavaScript自動化(JXA)腳本
- 16. 的Windows 10 - 自動退出批處理腳本
- 17. Mac bash腳本 - 每2分鐘自動執行右箭頭鍵
- 18. 爲什麼我的Perl腳本以137退出?
- 19. 如何在調用Perl腳本後退出命令shell?
- 20. 從Java執行Perl腳本tomcat返回255退出代碼
- 21. 如何在perl腳本退出之前運行一段代碼
- 22. 任何從VB6 IDE退出時自動運行腳本/ EXE的方法?
- 23. bash:退出腳本循環
- 24. CasperJS腳本永不退出
- 25. Tcsh腳本不會退出
- 26. Node.js腳本不退出
- 27. 退出整個腳本{}
- 28. PHP腳本退出過快
- 29. 管道的Perl腳本日誌僅運行,每2次點擊
- 30. Perl - 使用來自perl腳本的rsync
你不需要寫一個腳本來殺死一個進程:'pkill -f [pattern]'(這個發送'SIGTERM',但是你可以指定你喜歡的任何信號)。不過,我很好奇,爲什麼你的腳本一次只運行幾個小時? – ThisSuitIsBlackNot
該腳本爲呼叫質量測試生成隨機VOIP呼叫 – EnigmaRenegade