是否有可能在C中使用系统api启动一个kill命令?如果没有其他选择的话
Is it possible a kill a command launched using system api in C? If not any alternatives?
我正在使用系统api启动命令(我可以使用这个api与C/c++ )。我传递的命令可能会挂起,因此我希望在超时后杀死它。
目前我使用的是:
system("COMMAND");
我想这样使用它:
使用系统独立的API运行命令(我不想使用CreateProcess,因为它仅适用于Windows)如果在'X'分钟后未退出,则杀死进程。
由于system()
是特定于平台的调用,因此不可能有独立于平台的方法来解决您的问题。然而,system()
是一个POSIX调用,所以如果它在任何给定的平台上都得到支持,那么POSIX API的其余部分也应该得到支持。因此,解决问题的一种方法是使用fork()
和kill()
。
system()
调用一个shell有一个复杂的地方,它可能会产生其他进程,我假设您想要杀死所有的进程,所以一种方法是使用一个进程组。基本思想是使用fork()
创建另一个进程,将其放在自己的进程组中,如果它在一定时间后没有退出,则杀死该进程组。
一个简单的例子——程序分叉;子进程将自己的进程组设置为与其进程ID相同,并使用system()
生成一个无限循环。父进程等待10秒,然后使用子进程PID的负值杀死进程组。这将终止分支进程和该进程的所有子进程(除非它们更改了它们的进程组)。
由于父进程在不同的组中,kill()
对它没有影响。
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
int main() {
pid_t pid;
pid = fork();
if(pid == 0) { // child process
setpgid(getpid(), getpid());
system("while true ; do echo xx ; sleep 5; done");
} else { // parent process
sleep(10);
printf("Sleep returnedn");
kill(-pid, SIGKILL);
printf("killed process group %dn", pid);
}
exit(0);
}
没有标准的、跨平台的系统API。提示是它们是系统api !我们实际上很"幸运",我们得到了system
,但我们没有得到其他任何东西。
你可以试着找一些第三方抽象
检查下面基于c++线程的linux尝试。(未测试)
#include <iostream>
#include <string>
#include <thread>
#include <stdio.h>
using namespace std;
// execute system command and get output
// http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
std::string exec(const char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
void system_task(string& cmd){
exec(cmd.c_str());
}
int main(){
// system commad that takes time
string command = "find /";
// run the command in a separate thread
std::thread t1(system_task, std::ref(command));
// gives some time for the system task
std::this_thread::sleep_for(chrono::milliseconds(200));
// get the process id of the system task
string query_command = "pgrep -u $LOGNAME " + command;
string process_id = exec(query_command.c_str());
// kill system task
cout << "killing process " << process_id << "..." << endl;
string kill_command = "kill " + process_id;
exec(kill_command.c_str());
if (t1.joinable())
t1.join();
cout << "continue work on main thread" << endl;
return 0;
}
我有一个类似的问题,在Qt/QML开发中:我想启动一个bash命令,同时继续在Qt循环中处理事件,如果bash命令花费的时间太长,就杀死它。
我想出了下面的课程,我在这里分享(见下文),希望它可能对有类似问题的人有所帮助。
我没有调用'kill'命令,而是调用开发人员提供的cleanupCommand。例如:如果我要调用myscript.sh并想要检查它是否持续运行不超过10秒,我将以以下方式调用它:
SystemWithTimeout systemWithTimeout("myScript.sh", 10, "killall myScript.sh");
systemWithTimeout.start();
代码:class SystemWithTimeout {
private:
bool m_childFinished = false ;
QString m_childCommand ;
int m_seconds ;
QString m_cleanupCmd ;
int m_period;
void startChild(void) {
int rc = system(m_childCommand.toUtf8().data());
if (rc != 0) SYSLOG(LOG_NOTICE, "Error SystemWithTimeout startChild: system returned %d", rc);
m_childFinished = true ;
}
public:
SystemWithTimeout(QString cmd, int seconds, QString cleanupCmd)
: m_childFinished {false}, m_childCommand {cmd}, m_seconds {seconds}, m_cleanupCmd {cleanupCmd}
{ m_period = 200; }
void setPeriod(int period) {m_period = period;}
void start(void) ;
};
void SystemWithTimeout::start(void)
{
m_childFinished = false ; // re-arm the boolean for 2nd and later calls to 'start'
qDebug()<<"systemWithTimeout"<<m_childCommand<<m_seconds;
QTime dieTime= QTime::currentTime().addSecs(m_seconds);
std::thread child(&SystemWithTimeout::startChild, this);
child.detach();
while (!m_childFinished && QTime::currentTime() < dieTime)
{
QTime then = QTime::currentTime();
QCoreApplication::processEvents(QEventLoop::AllEvents, m_period); // Process events during up to m_period ms (default: 200ms)
QTime now = QTime::currentTime();
int waitTime = m_period-(then.msecsTo(now)) ;
QThread::msleep(waitTime); // wait for the remaning of the 200 ms before looping again.
}
if (!m_childFinished)
{
SYSLOG(LOG_NOTICE, "Killing command <%s> after timeout reached (%d seconds)", m_childCommand.toUtf8().data(), m_seconds);
int rc = system(m_cleanupCmd.toUtf8().data());
if (rc != 0) SYSLOG(LOG_NOTICE, "Error SystemWithTimeout 164: system returned %d", rc);
m_childFinished = true ;
}
}
我不知道在C或c++语言中有任何可移植的方法来做到这一点。当你要求替代时,我知道在其他语言中是可能的。例如,在Python中,可以使用subprocess
模块。
import subprocess
cmd = subprocess.Popen("COMMAND", shell = True)
你可以测试COMMAND是否以
结尾if cmd.poll() is not None:
# cmd has finished
你可以用:
cmd.terminate()
即使你更喜欢使用C语言,你也应该阅读subprocess模块的文档,因为它解释了它在Windows系统上使用CreateProcess
和Posix系统上使用os.execvp
来启动命令,在Windows系统上使用TerminateProcess
和Posix系统上使用SIG_TERM
来停止命令。
- 从命令行c++发送文本文件名
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 使用QProcess执行命令,并将结果存储在QStringList中
- 数组长度,为什么从命令行获取时不能使用它?
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- clang整洁10忽略了我的NOLINT命令
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- 如何处理linux终端中带有负号(-)的C++中的命令行参数
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 使用VS Code和CMake Tools运行自定义命令
- 如何使用ESP8266向谷歌主页发送命令
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 通过 Openssl 命令行加密,通过 c++ 解密
- CMake "--target install"无需"--build"命令行
- Gstreamer 管道从命令 lne 到 c 代码
- 自动"yes"到 Popen SSH 命令
- 是否有可能在C中使用系统api启动一个kill命令?如果没有其他选择的话