Linux附带了大量命令,每个命令都是唯一的,并在特定情况下使用。Linux timeout命令的一个属性是时间限制。可以为任何命令设置时间限制。如果时间到期,命令将停止执行。
如何使用timeout命令
我们将解释如何使用Linux timeout命令
timeout [OPTION] DURATION COMMAND [ARG]…
timeout [OPTION]
DURATION可以是正整数或浮点数,后跟可选的单位后缀:
s - seconds (default)
m - minutes
h - hours
d - days
未使用单位时,默认为秒。如果持续时间设置为零,则禁用关联的超时。
其他选项
DESCRIPTION
--preserve-status
以与COMMAND相同的状态退出,即使命令超时
--foreground
当不直接从shell提示符运行超时时,允许COMMAND从TTY读取并获得TTY信号;在此模式下,COMMAND的子级不会超时
-k, --kill-after=DURATION
如果COMMAND仍在运行,也发送KILL信号在发出初始信号后很久
-s, --signal=SIGNAL
指定超时时要发送的信号;SIGNAL可以是类似“HUP”的名称或数字;有关信号列表,请参见“kill-l”
--help
显示此帮助并退出
--version
输出版本信息并退出
如何使用timeout命令的基本示例
- 1.设置定时间后终止命令:
timeout 30 ping www.baidu.com
通过使用超时,我们可以确保ping不会一直运行,占用网络带宽并纠缠任何正在ping的设备。
此命令允许ping运行五秒钟。它正在对www.baidu.com的域名进行ping,用于研究本文的测试网络上。
如果程序的执行在超时终止之前结束,超时可以将退出代码从程序传递回shell,要实现这一点,程序必须自动停止(换句话说,它不会因超时而终止),并且必须使用–preserve-status选项。
如果使用值为5的-c(count)选项,ping将只发出5个请求。如果我们给超时一分钟,ping肯定会自行终止。然后我们可以使用echo检查退出值。
- 2.发送正确的信号
当timeout想要停止程序时,它会发送SIGTERM信号。这礼貌地要求程序终止。某些程序可能选择忽略SIGTERM信号。
我们可以通过请求超时来发送SIGKILL信号来实现这一点。可以使用-s(signal)选项告诉超时以发送SIGKILL信号。
timeout -s SIGKILL 20 sudo tcpdump -i ens33 -n -w 20230212.pcap
我们可以使用tcpdump 抓包的默认选项运行20秒后,发送SIGKILL信号终止进程。
- 3.尝试使用SIGTERM停止程序
我们使用-k(kill after)选项。-k选项需要一个时间值作为参数。在这个命令中,我们要求超时,让dmesg运行30秒,然后用SIGTERM信号终止它。如果dmesg在40秒后仍在运行,则意味着外交SIGTERM被忽略,超时应发送SIGKILL以完成任务。
timeout -k 40 30 dmesg -w
dmesg运行30秒,并在收到SIGTERM信号时停止。
Linux C/C++ timeout命令实现
...
int main(int argc, char** argv) {
...
for(int i=1;i<argc;i++) {
char* arg = argv[i];
if(strlen(arg) <= 0) continue;
if(arg[0] == '-') {
if(!strcmp(arg, "-h") || !strcmp(arg, "--help")) {
printHelp(argv[0]);
return EXIT_SUCCESS;
} else if(!strcmp(arg, "-9") || !strcmp(arg, "--kill")) {
sig_kill = SIGKILL;
...
} else {
fprintf(stderr, "Illegal argument: %s\n", arg);
return EXIT_FAILURE;
}
} else {
/*
没有更多选项。检查是否有足够的剩余参数
基本语法是/程序[OPTIONS]超时程序[ARGS]
而超时和程序是强制性的 */
if (i+2 > argc) { // 检查是否给出超时和程序
fprintf(stderr, "Not enough arguments. Check %s --help, if you need help\n", argv[0]);
if(i+1 > argc) {
// 检查参数是否为数字
fprintf(stderr, " Missing: TIMEOUT PROGRAM\n");
} else {
if(is_numeric(argv[i]))
fprintf(stderr, " Missing: PROGRAM\n");
else
fprintf(stderr, " Missing: TIMEOUT\n");
}
return EXIT_FAILURE;
} else {
int seconds = atoi(argv[i]);
if(seconds < 0) {
fprintf(stderr, "Timeout cannot be negative");
return EXIT_FAILURE;
}
timeout = (unsigned int)seconds;
// 合并程序和可选程序参数
for(int j=i+1;j<argc;j++)
command = strappend(command, argv[j]);
break;
}
}
}
// 检查程序参数
if(command == NULL || strlen(command) <= 0) {
fprintf(stderr, "Not enough arguments. Check %s --help, if you need help\n", argv[0]);
fprintf(stderr, " Missing: TIMEOUT PROGRAM\n");
return EXIT_FAILURE;
}
// Fork守护程序(如果需要)
if (daemonize) {
fork_daemon();
}
...
int status;
pid_t wait_status;
// 信号处理器
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGALRM, sig_handler);
if(verbose) printf("Child process forked with pid %d.\n", proc_pid);
// 设置报警
if(timeout > 0) alarm(timeout);
wait_status = waitpid(proc_pid, &status, 0); // Wait for child
runtime += millis();
if(wait_status < 0) {
fprintf(stderr, "Error waiting for process: %s\n", strerror(errno));
return EXIT_FAILURE;
}
status = WEXITSTATUS(status); // 获取实际退出状态
if(status != 0) {
if(verbose) fprintf(stderr, "Process exited with status %d after %ld milliseconds\n", status, runtime);
return status;
} else {
if(verbose) printf("Process completed after %ld milliseconds\n", runtime);
return status;
}
}
...
}
...
static void sig_handler(int sig_no) {
switch(sig_no) {
case SIGALRM:
// Timeout
if(verbose)
printf("TIMEOUT after %ld milliseconds.\n", runtime+millis());
else
printf("TIMEOUT\n");
terminate_process();
exit(EXIT_FAILURE);
break;
case SIGINT:
case SIGTERM:
if(proc_pid <= 0) exit(EXIT_FAILURE);
if(verbose) printf("Program termination request\n");
if(proc_pid > 0) kill(proc_pid, sig_no);
exit(EXIT_FAILURE);
return;
}
}
...
编译运行
If you need the complete source code of timeout, please add WeChat number (c17865354792)
总结
总结
timeout是一个命令行实用程序,它运行指定的命令,如果在给定的时间段后仍在运行,则终止该命令。
Welcome to follow WeChat official account【程序猿编码】