Оболочка никогда не видит Ctrl-C
.Он интерпретируется (псевдо) -терминалом и преобразуется в SIGINT
, после чего выполняется действие.
Локально запускайте программу в под-оболочке, которая сообщает о своем pid, а затем используйте этот 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();
}
С помощью ssh, поскольку вам нужно переслать сигнал удаленному процессу, и, таким образом, вам необходим удаленный управляющий терминал (ssh -t
).И для что вы будете отправлять Ctrl-C
, что удаленный терминал будет интерпретировать как правильный сигнал.