隐藏 sh: -c 在 c++ Linux 中调用“system”时的错误消息
Hide sh: -c error messages when calling “system” in c++ Linux
我正在使用系统来执行带有参数的命令。我不想使用exec/fork。当我的命令中有不匹配的引号时,会出现此错误:
sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file
如何抑制这些外壳的错误消息? 我尝试在无效命令的末尾添加>/dev/null 2>&1
,但它没有禁止显示 shell 错误消息。 对于后台,我正在运行用户提供的命令,这些命令可能有效,也可能无效。 我无法提前知道它们是否有效,但无论如何我都想抑制错误消息。
下面是生成我试图禁止显示的错误类型的代码示例:
int main()
{
// This command is meant to be invalid as I'm trying to suppress the shell syntax error message
system("date ' >/dev/null 2>&1");
return 0;
}
你可以帮我吗?
认为system
分叉一个进程,然后执行你提供的命令。新进程从其父进程继承描述符,并且该新进程正在写入其标准错误。
因此,此代码片段可能会执行您想要的操作:
#include <stdlib.h>
#include <unistd.h>
int main()
{
int duperr;
duperr = dup(2);
close(2); /* close stderr so the new process can't output the error */
system("date '");
dup2(duperr, 2);
close(duperr);
/* here you can use stderr again */
write(2, "hello worldn", 12);
return 0;
}
要以静默方式抑制对 stderr 的写入,您可以将错误输出到 /dev/null
:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
int devnull_fd, duperr_fd;
/* get a descriptor to /dev/null (devnull_fd) */
devnull_fd = open("/dev/null", O_WRONLY | O_APPEND);
/* save a descriptor "pointing" to the actual stderr (duperr_fd) */
duperr_fd = dup(STDERR_FILENO);
/* now STDERR_FILENO "points" to "/dev/null" */
dup2(devnull_fd, STDERR_FILENO);
system("date '");
/* restore stderr */
dup2(duperr_fd, STDERR_FILENO);
close(duperr_fd);
close(devnull_fd);
/* here you can use stderr again */
write(STDERR_FILENO, "hello worldn", 12);
return 0;
}
请记住检查函数调用的返回值。
逻辑问题是您没有重定向任何内容,因为>/dev/null 2>&1
部分最终包含在单引号部分中。
然而,字符串没有结束,因此 bash 在 stderr 上抱怨。
这种特定情况的解决方案是通过在单引号前面加上反斜杠来引用单引号,即调用 system("date ' >/dev/null 2>&1")
。但请注意,bash精确引用规则是一场小噩梦。
我通常可以想到的一种解决方法是将命令保存在文件中,例如cmd.txt
,然后执行
system("bash < cmd.txt >/dev/null 2>&1");
也许这也可以用bash -c
在不创建文件的情况下完成,但我根本无法理解-c
的单引号转义规则,我不会在完全破碎的bash
语法上浪费神经元。
您可能希望运行正确的命令,然后删除引号,因此
system("date >/dev/null 2>&1");
但是,运行它有什么意义呢?如果(您的PATH
足够常见,以便... date
确实是/bin/date
(参见 date(1)...),它的唯一效果是产生一些输出,而您通过将其重定向到 /dev/null
来丢弃它。因此,调用system
的唯一可见效果是花费数百万个 CPU 周期。当然,在奇怪的情况下,它可能会失败(例如,因为/bin/sh
不存在,/bin/date
不存在,fork
失败了,等等......
也许你正在编写一个外壳。然后你应该解析命令并做fork
和execve
.....
如果你想获取一些命令的输出,比如 date
,最好使用 popen(3) 和 pclose
。在 date
的特殊情况下,使用 time(2)、localtime(3)、strftime(3) 要好得多(这样你就不需要依赖外部命令,也不需要使用 popen
)
如果你真的想抑制由system
启动的shell的输出,你可以自己做fork
和execve
(bin/sh -c
),并使用dup2
重定向标准和错误输出(到文件描述符打开/dev/null
)。参见 daemon(3) 和 wordexp(3)
也许在你的应用程序中嵌入一个解释器(例如.lua或诡计)会更明智(假设你不关心用户错误)
- boost::进程间消息队列引发错误
- 在线编译器中的分段C++没有打印消息
- C++错误消息*成员参考.**初学者*
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何通过参数抛出错误消息
- 从服务器传输到客户端的消息不会出现
- 如何在c++中使用system()来运行包含空格的python脚本
- System.InvalidCastException - SQL to C++ - safe_cast<float>
- ROS2 动态消息模板
- C++秘密消息学校作业
- glad 导致 glfwSwapBuffers 返回错误消息
- C++入门 5 版:类消息和文件夹
- FindPackageHandleStandardArgs.cmake:137 的 CMake 错误(消息):找不到 Boost (缺少:正则表达式)(找到合适的版本"1.72.0",
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 如何接受 [ENTER] 键作为无效输入并发送错误消息
- C++/CLI System.AccessViolation在托管类中调用非托管函数时出现异常
- 由于无效的 ValidateRgn() 子窗口不会收到WM_PAINT消息
- 隐藏 sh: -c 在 c++ Linux 中调用“system”时的错误消息
- System.IO.FileNotFoundException未经处理消息=“找不到指定的模块.(HRESULT中的异常