【问题标题】:C++ executing a bash script which terminates and restarts the current processC++ 执行一个 bash 脚本,该脚本终止并重新启动当前进程
【发布时间】:2013-07-09 19:52:27
【问题描述】:

所以情况就是这样,我们有一个 C++ 数据馈送客户端程序,我们使用不同的参数运行大约 30 个实例,并且编写了 3 个脚本来运行/停止它们:start.sh stop.sh 和 restart.sh (它运行 stop.sh 然后 start.sh)。

当有大量数据时,客户端会实时“落后”。我们通过将系统时间与列出的最新数据输入时间进行比较来测试这一点。如果任何客户端落后超过 10 分钟左右,我想调用重新启动脚本以重新启动所有二进制文件,以便我们的数据尽可能接近实时。

通常我使用 System(script.sh) 调用脚本,但是重新启动脚本会查找并使用 kill 杀死进程,但是调用 System() 也会使当前程序执行忽略 SIGQUIT 和 SIGINT,直到 system() 返回。

最重要的是,如果有两个具有相同参数的并发执行它们将发生冲突并且程序将挂起(这源于建立数据库连接),所以我无法启动新实例,直到旧实例被杀死并且我如果忽略 SIGQUIT,则无法杀死当前的。

有没有办法解决这个问题?二进制文件的当前状态和丢失的一些数据如果达到阈值则根本无关紧要,我也不能让程序自行重新启动,因为如果其中一个实例落后,我们想重新启动所有 30 个实例(因此数据中的差距在同一时间)。有没有一种干净的方法可以从 C++ 中调用脚本,交出控制权并允许脚本从头开始重新启动程序?

仅供参考,我们在 CentOS 6.3 上运行

【问题讨论】:

  • 而不是从 30 个实例之一运行脚本,您可以派生并在一个新进程中执行此操作,该进程将在从 System 返回后退出,或者您可以让调用 system 的实例终止?
  • 重新构建客户端以检查时间本身可能会更好,如果它落后得太远,要么跳过足够的数据以赶上或以某种方式重新启动自身(re-exec()- ing 本身是一种方法,但最好考虑是否需要先对文件、连接、套接字等进行任何清理......)。

标签: c++ linux bash shell


【解决方案1】:

使用exec() 代替system()。它将用新的流程替换您的流程。请注意,exec() 的调用方式及其行为方式存在显着差异:system() 将其字符串参数传递给系统 shell 以运行。 exec() 实际上执行一个可执行文件,您需要一次向进程提供一个参数,而不是让 shell 为您解析它们。

【讨论】:

  • execve() 似乎是正确的选择。没有要传递的参数,因为所有内容都包含在脚本中,所以我发送一个 null 作为可执行参数,但是我不确定在调用时如何设置环境变量..
  • 您可以尝试使用空字符串作为环境变量,也可以将当前进程的环境传递给extern char **environ;,换句话说,execve(filename, argv, environ);
【解决方案2】:

这是我的两分钱。

临时解决方案:使用 SIGKILL。
长期解决方案:优化您的代码服务树的一般逻辑,使用其他系统调用,如 exec 或重写它以使用 threads

如果你想要更好的答案,也许你应该发布一些代码和或去概括这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 2015-08-25
    • 2014-02-18
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多