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【程式猿編碼】