我有一个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