伙伴云客服论坛»论坛 S区 S软件开发 查看内容

0 评论

0 收藏

分享

Linux C/C++ timeout命令实现运行具有时间限制功能

目录

    Linux C/C++ timeout命令实现运行具有时间限制
      如何使用timeout命令如何使用timeout命令的根本示例
        1.设置定时间后终止命令:2.发送正确的信号3.尝试使用SIGTERM停止程序
      总结
    扩展:Linux运行有时间限制的命令—timeout命令
      当我们想让一个定时的crontab任务运行运行一段时间后,自动终止? 有两种方案:



Linux C/C++ timeout命令实现运行具有时间限制

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的设备。
Linux C/C++ timeout命令实现运行具有时间限制功能-1.jpg

此命令允许ping运行五秒钟。它正在对www.baidu.com的域名停止ping,用于研究本文的测试网络上。
假设程序的执行在超时终止之前完毕,超时可以将退出代码从程序传送回shell,要实现这一点,程序必需自动停止(换句话说,它不会因超时而终止),并且必需使用–preserve-status选项。
假设使用值为5的-c(count)选项,ping将只发出5个恳求。假设我们给超时一分钟,ping肯定会自行终止。然后我们可以使用echo检查退出值。
Linux C/C++ timeout命令实现运行具有时间限制功能-2.png


2.发送正确的信号

当timeout想要停止程序时,它会发送SIGTERM信号。这礼貌地要求程序终止。某些程序可能选择忽略SIGTERM信号。
我们可以通过恳求超时来发送SIGKILL信号来实现这一点。可以使用-s(signal)选项告诉超时以发送SIGKILL信号。
timeout -s SIGKILL 20 sudo tcpdump -i ens33 -n -w 20230212.pcap
Linux C/C++ timeout命令实现运行具有时间限制功能-3.png

我们可以使用tcpdump 抓包的默认选项运行20秒后,发送SIGKILL信号终止进程。

3.尝试使用SIGTERM停止程序

我们使用-k(kill after)选项。-k选项需要一个时间值作为参数。在这个命令中,我们要求超时,让dmesg运行30秒,然后用SIGTERM信号终止它。假设dmesg在40秒后仍在运行,则意味着外交SIGTERM被忽略,超时应发送SIGKILL以完成任务。
timeout -k 40 30 dmesg -w
Linux C/C++ timeout命令实现运行具有时间限制功能-4.jpg

dmesg运行30秒,并在收到SIGTERM信号时停止。
Linux C/C++ timeout命令实现
...
int main(int argc, char** argv) {
...
    for(int i=1;i<argc;i++) {
            char* arg = argv;
            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))
                                                fprintf(stderr, "  Missing: PROGRAM\n");
                                        else
                                                fprintf(stderr, "  Missing: TIMEOUT\n");
                                }
                                return EXIT_FAILURE;
                    } else {
                                int seconds = atoi(argv);
                                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;
        }
}

...

编译运行
Linux C/C++ timeout命令实现运行具有时间限制功能-5.png

If you need the complete source code of timeout, please add WeChat number (c17865354792)​

总结

timeout是一个命令行实用程序,它运行指定的命令,假设在给定的时间段后仍在运行,则终止该命令。

扩展:Linux运行有时间限制的命令—timeout命令


当我们想让一个定时的crontab任务运行运行一段时间后,自动终止? 有两种方案:

一、启动一个进程任务,然后在启动一个杀死进程任务
二、使用linux中的timeout命令
示例:执行crontab -e 进入定时任务,添加如下命令
30 9 * * * timeout -s SIGKILL 12h /home/pirate/programs/hadoop/bin/hdfs balancer -threshold 10  > ~/balancer-stdout.log 2>~/balancer-stderr.log &
32 9 * * * /home/pirate/programs/hadoop/bin/hdfs dfsadmin -setBalancerBandwidth 304857600到此这篇关于Linux C/C++ timeout命令实现(运行具有时间限制)的文章就介绍到这了,更多相关Linux运行行具有时间限制内容请搜索网站以前的文章或继续阅读下面的相关文章希望大家以后多多支持网站!

回复

举报 使用道具

相关帖子
全部回复
暂无回帖,快来参与回复吧
本版积分规则 高级模式
B Color Image Link Quote Code Smilies

微黄
注册会员
主题 13
回复 20
粉丝 0
|网站地图
快速回复 返回顶部 返回列表