Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用QProcess将EndOfText(Ctrl-C)发送到交互式shell_C++_Bash_Qt_Shell_Qprocess - Fatal编程技术网

C++ 使用QProcess将EndOfText(Ctrl-C)发送到交互式shell

C++ 使用QProcess将EndOfText(Ctrl-C)发送到交互式shell,c++,bash,qt,shell,qprocess,C++,Bash,Qt,Shell,Qprocess,我使用QProcess打开/bin/sh或/usr/bin/bash,可以将命令写入shell并将输出读取到我的程序中 实际问题发生在尝试向shell发送文本结束控制信号以中止shell正在运行的子进程时 我尝试的是: shell将在-i交互激活模式下启动 我使用shell内置的set-m命令来启用作业控制 出于调试目的,我读取了$-变量,它似乎是himBHs 发送任意命令通常有效(例如ls) 发送\x04(传输结束,Ctrl+D)会起作用并杀死外壳 如何在不再次打开shell的情况下恰当地

我使用QProcess打开
/bin/sh
/usr/bin/bash
,可以将命令写入shell并将输出读取到我的程序中

实际问题发生在尝试向shell发送文本结束控制信号以中止shell正在运行的子进程时

我尝试的是:

  • shell将在
    -i
    交互激活模式下启动
  • 我使用shell内置的
    set-m
    命令来启用作业控制
  • 出于调试目的,我读取了
    $-
    变量,它似乎是
    himBHs
  • 发送任意命令通常有效(例如
    ls
  • 发送
    \x04
    (传输结束,Ctrl+D)会起作用并杀死外壳
如何在不再次打开shell的情况下恰当地终止正在运行的进程

QProcess process;
process.start("/bin/sh", QStringList() << "-i");
process.write("set -m\necho $-\n");                 // returns himBHs
process.waitForBytesWritten();

// start a running program here (E.g. tail -f logfile)
process.write("tail -f logfile\n");

process.write("\x03");
process.write("newcommand\n");
process.waitForBytesWritten();
QProcess过程;

process.start(“/bin/sh”,QStringList()shell永远不会看到
Ctrl-C
。它由(伪)终端解释并转换为,然后对其执行操作

在本地,在报告其pid的子shell中启动程序,然后使用该pid直接杀死它

#include <QtCore>
#include <signal.h>
#include <cstdio>

int getPID(const QByteArray &line) {
   int pid = 0;
   char c1, c2;
   if (sscanf(line.data(), "@@@%d@@%c%c", &pid, &c1, &c2) == 3)
      if (c1 == '@' && (c2 == '\r' || c2 == '\n')) return pid;
   return 0;
}

int main(int argc, char *argv[]) {
   auto input = QByteArray(
                    "echo _kill_me_now_ > log\n"
                    "/bin/sh -c 'echo @@@$$@@@>&2; exec tail -f log'\n"
                    "echo done\n"
                    "exit\n")
                    .split('\n');
   // tail -f will block

   QCoreApplication app(argc, argv);
   QProcess process;
   int pid = 0;

   auto const writeInputLine = [&] {
      if (input.isEmpty()) return;
      auto const line = input.takeFirst();
      puts(line.data());
      fflush(stdout);
      process.write(line);
      process.write("\n");
   };

   process.setProcessChannelMode(QProcess::SeparateChannels);
   QObject::connect(&process, &QProcess::stateChanged, [](auto state) {
      auto static const meta = QMetaEnum::fromType<QProcess::ProcessState>();
      fprintf(stderr, "State=%s\n", meta.key(state));
      fflush(stderr);
      if (state == QProcess::NotRunning) QCoreApplication::quit();
   });
   QObject::connect(&process, &QProcess::readyReadStandardError, [&] {
      auto const data = process.readAllStandardError();
      if (auto p = getPID(data)) pid = p; // we could suppress pid output here
      fputs(data.data(), stdout);
      fflush(stdout);
      if (data.endsWith("$ ")) writeInputLine();
   });
   QObject::connect(&process, &QProcess::readyReadStandardOutput, [&] {
      while (process.canReadLine()) {
         auto const line = process.readLine();
         fputs(line.data(), stdout);
         if (line.startsWith("_kill_me_now_") && pid) {
            kill(pid, SIGTERM);
            pid = 0;
         }
      }
      fflush(stdout);
   });

   process.start("/bin/sh", {"--noediting", "-i"});
   return app.exec();
}
#包括
#包括
#包括
int getPID(常数QByteArray和line){
int-pid=0;
字符c1,c2;
如果(sscanf(line.data(),“@@@d@@@c%c”,&pid,&c1,&c2)==3)
如果(c1='@'&&(c2='\r'| c2='\n'))返回pid;
返回0;
}
int main(int argc,char*argv[]){
自动输入=QByteArray(
“echo\u kill\u me\u now\u>日志\n”
“/bin/sh-c'echo@$@@@@2;exec tail-f log'\n”
“回显完成\n”
“退出\n”)
.split('\n');
//tail-f将阻塞
QCore应用程序应用程序(argc、argv);
QProcess过程;
int-pid=0;
自动常量writeInputLine=[&]{
if(input.isEmpty())返回;
auto const line=input.takeFirst();
put(line.data());
fflush(stdout);
进程。写入(行);
进程。写入(“\n”);
};
process.setProcessChannelMode(QProcess::SeparateChannels);
QObject::connect(&process,&QProcess::stateChanged,[](自动状态){
自动静态常量meta=QMetaEnum::fromType();
fprintf(stderr,“State=%s\n”,meta.key(State));
fflush(stderr);
if(state==QProcess::NotRunning)QCoreApplication::quit();
});
QObject::connect(&process,&QProcess::readyReadStandardError,[&]{
auto const data=process.readAllStandardError();
如果(auto p=getPID(data))pid=p;//我们可以在这里抑制pid输出
fputs(data.data(),stdout);
fflush(stdout);
如果(data.endsWith($)writeInputLine();
});
QObject::connect(&process,&QProcess::readyReadStandardOutput,[&]{
while(process.canReadLine()){
auto const line=process.readLine();
fputs(line.data(),stdout);
if(line.startsWith(“\u kill\u me\u now”&&pid){
kill(pid,SIGTERM);
pid=0;
}
}
fflush(stdout);
});
process.start(“/bin/sh”,{--noediting”,“-i”});
返回app.exec();
}
使用ssh,由于您需要将信号转发到远程进程,因此您需要一个远程控制终端(
ssh-t
)。对于,您将发送一个
Ctrl-C
,远程终端将重新解释为一个正确的信号