Вопрос по c++, linux, terminal – Команда работает в терминале, но не через QProcess

18
ifconfig | grep 'inet'

работает при исполнении через терминал. Но не через QProcess

Мой пример кода

QProcess p1;
p1.start("ifconfig | grep 'inet'");
p1.waitForFinished();
QString output(p1.readAllStandardOutput());
textEdit->setText(output);

Ничего не отображается на textedit.

но когда я использую толькоifconfig при запуске qprocess вывод выводится на textedit. Я пропустил какой-то трюк, чтобы построить командуifconfig | grep 'inet' нравится использовать\' за' а также\| за|? для специальных символов? но я тоже это попробовал :(

возможный дубликатQprocess messes my linux command up (i think). how to fix? J-16 SDiZ
вам нужно указать полный путь для ifconifg. Ваше приложение имеет другую переменную PATH, чем ваш терминал Kamil Klimek
@KamilKlimek Поскольку это может быть проблемой для отдельных команд, в этом случае передача команд (которая не поддерживается QProcess) является реальной проблемой. leemes
Если вы хотите получить ipaddress, используйте правильный способ:qt-project.org/doc/qt-4.8/qnetworkinterface.html J-16 SDiZ
Правильно! полностью забыл об этом Kamil Klimek

Ваш Ответ

3   ответа
39

что вы пытаетесь сделать, это выполнитьshell commandне процесс. Передача команд является особенностью вашей оболочки.

Есть три возможных решения:

Поместите команду, которую вы хотите выполнить в качестве аргументаsh после-c (& Quot; команда & Quot;):

QProcess sh;
sh.start("sh", QStringList() << "-c" << "ifconfig | grep inet");

sh.waitForFinished();
QByteArray output = sh.readAll();
sh.close();

Или вы можете написать команды в качестве стандартного ввода дляsh:

QProcess sh;
sh.start("sh");

sh.write("ifconfig | grep inet");
sh.closeWriteChannel();

sh.waitForFinished();
QByteArray output = sh.readAll();
sh.close();

Другой подход, который избегаетsh, чтобы запустить два QProcesses и выполнить конвейер в вашем коде:

QProcess ifconfig;
QProcess grep;

ifconfig.setStandardOutputProcess(&grep); // "simulates" ifconfig | grep

ifconfig.start("ifconfig");
grep.start("grep", QStringList() << "inet"); // pass arguments using QStringList

grep.waitForFinished(); // grep finishes after ifconfig does
QByteArray output = grep.readAll(); // now the output is found in the 2nd process
ifconfig.close();
grep.close();
@AkiRoss Закрытие stdin также выполнит то, что "в последней строке". Просто попробуйте в своем терминале:echo -n 'ifconfig | grep inet' | sh, гдеecho -n пропускает разрыв строки. Однако впоследствии он завершится, и канал между echo и sh закроет поток stdin sh.
Я добавил примеры кода для некоторых возможных решений.
@AkiRoss Большое спасибо за ваш вклад, вы правы. (2): я думаю, проблема в том, чтоsh ждет больше команд на стандартный ввод. Вы должны закрыть канал stdin shsh.closeWriteChannel() между записью и ожиданием. (1): я на 95% уверен, что\n не обязательно. (1) + (2): если вы делаетеnot закрыть стандартный вводnot написать новую строку, кажется, ничего не происходит. Если вы это сделаете, команда будет выполнена, но только закрытие stdin sh'а завершит работу sh после выполнения. Поэтому, если мы решим (2), нам не нужно заботиться о (1). Если мы хотим выполнить несколько команд, мы должны исправить (1), но не (2).
Grep сработал. Но я хочу передать вывод ifconfig в awk '/ inet / {gsub (/.*:/,& quot; & quot; ", $ 1); print $ 1}". который успешно напечатал некоторые o / p на терминале, а не через Qprocess. Я использовал меня 2 твоего решения ScarCode
Я считаю, что второй пример неверен: если вы запускаете оболочку и пишете в нее, вам также необходимо (1) отправлять команды в оболочку, добавляя символы новой строки и (2) завершать оболочку послеgrep команда выполнена, илиwaitForFinished() буду ждать вечно. Я провел быструю проверку, чтобы убедиться, что ваш код работает, и это не для меня, но исправьте меня, если я ошибаюсь :)
7

QProcess объект не дает автоматически полный синтаксис оболочки: вы не можете использовать каналы. Используйте оболочку для этого:

Ах да, это должны быть двойные кавычки, а не кавычки.
Я тоже это попробовал. но все еще не работает !! ScarCode
альтернатива (безопаснее, так как вам не нужно обращать внимание на экранирование внутри аргумента, если он более сложный): используйте QStringList для аргументов, например так:p1.start("/bin/sh", QStringList() << "-c" << "ifconfig | grep inet");
5

Однако естьsetStandardOutputProcess Метод, который направит вывод в следующий процесс.

Пример приведен в API.

Похожие вопросы