如何从C程序执行命令

时间:2015-12-15 09:17:01

标签: c bash

直接从用ANSI C编写的程序执行'trap -p'等命令的最佳方法是什么? 我试过了:

Toolbar

但是当我添加系统(“bash”)时程序消失了。如何防止它降低成本或执行此类命令的更好方法是什么?

编辑:

谢谢大家的帮助。

有关我打算实现的目标的更多细节: 我希望能够: - 在我的程序中添加新的陷阱(陷阱仅在我的程序中工作) -display当前设置了陷阱(再次,我的程序中的陷阱)

这有可能以相对简单的方式实现吗?

3 个答案:

答案 0 :(得分:2)

  

但是当我添加系统(“bash”)程序消失时

是的,bash现在正在运行,你的C程序正在等待它终止。它似乎已经消失了,因为你会在你的终端上看到一个新的shell运行。尝试输入exit,您的C程序将继续。您可以通过在system("bash");之后添加打印语句来确认这一点。

您可以通过为bash指定trap -p选项来获取-i来生成输出,这使其成为一个交互式shell:

system("bash -i -c 'trap -p'");

从这看起来似乎trap需要一个tty,非交互式bash没有。

或者您可以将trap命令放在脚本中并按如下方式运行:

system("bash script.sh");

script.sh的内容:

echo Before setting trap...
trap -p
trap somecmd SIGINT
echo After setting a trap...
trap -p

在输出中你应该看到最初没有设置陷阱(假设没有从运行你的C程序的shell继承),然后trap应该显示新创建的陷阱。

答案 1 :(得分:1)

似乎您正在寻找一种在非交互式Bash shell中运行bash的方法,而不是运行交互式trap -p。这是你如何做到的。

system("bash -c 'trap -p'");

但是,trap -p输出中将无法显示您的C级信号处理程序。 Bash只能知道在Bash中定义的陷阱处理程序;你正在启动的shell将没有任何(除非它们是从你用来启动你的C程序的shell继承的。)

答案 2 :(得分:1)

我猜你是在Linux或其他POSIX系统上

通过阅读Advanced Linux Programming,您应该更好地了解Linux编程。您似乎误解了processessignals

你无法从某个shell(你的父shell或任何以system(3)开头的子shell中捕获运行你的C程序的进程内的信号。所以来自任何shell的trap -p的输出都不是与您的程序相关(但对于运行它的shell)。因此,即使使用FILE*fp = popen("trap -p", "r");,如popen("bash -i -c 'trap -p'", "r")(或fp ....),也请阅读pclose(和最后sig_atomic_t - 它是无用的。

如果您想处理C程序中的信号,请先仔细阅读 popen(3);然后阅读POSIX signal(7)文档(注意SIGSEGV);另请阅读signal.hsigaction(2)fork(2)

  

我希望能够:在我的程序中添加新的陷阱

这对在Linux或POSIX上运行的C程序没有意义。 C程序可以处理(非常谨慎和谨慎!)一些execve(2),这些不是陷阱。

  

[我想:] 显示当前设置的陷阱

同样,“陷阱”在C或C ++程序中没有任何意义,但是signals可以。您实际上不需要显示当前设置的信号处理程序,因为您之前已经设置过它们。 signals接受第三个 oldact 指针来保存之前的信号操作。

处理器 sigaction(2)(仅由内核代码处理,而不是由应用程序代码处理)远程间接相关信号。例如,traps(用于实现page fault)通常由内核处理以使用磁盘(文件或交换区域)中的页面填充virtual memory,但可以转换为{发送到进程的{1}}信号(对于page cache),通常以segmentation fault终止。

如果在C程序中安装了一些信号处理程序,请务必了解什么是异步信号安全函数(唯一允许您从信号处理程序调用的函数;特别是调用fprintfmalloc - 即使间接 - 是被禁止的,core dump也是如此。处理信号的一种有用方法是声明一些volatile sig_atomic_t变量并将它们设置在信号处理程序中(并在之外测试和重置,例如在事件循环中)。

shell trap undefined behavior用于管理某些 builtin(以及退出和错误条件)。要管理C中的信号,请使用signals。要在sigaction(2)时间运行某些内容,请使用exit(3)。要处理错误情况,请务必测试每个atexit(3)和大多数库函数(例如syscalls(2)scanf(3)等等...,请参阅malloc(3)),使用{{ 3}}