Не удается выполнить команду эха в QProcess

Я хочу запустить команду SCPI на своем устройстве с помощью утилиты netcat под Ubuntu 10.04 LTS с Qt. Мой код выглядит так:

env = "echo TRIG | nc 192.168.1.100 23 -q1";
process1.execute(env);
process1.waitForFinished(1000);

Эта команда не возвращает никаких данных, а просто запускает сбор данных. При использовании терминала с той же командой «echo TRIG | nc 192.168.1.100 23 -q1» все работает нормально. Из Qt не работает. Вывод отладки: "TRIG | nc 10.0.3.250 23 -q1"... так что без "эха". Мое устройство не получает команду TRIG.

Не могли бы вы посоветовать, что я делаю неправильно? Большое спасибо.


person user2655700    schedule 29.10.2013    source источник
comment
Дубликат stackoverflow. ком/вопросы/10701504/   -  person Frank Osterfeld    schedule 29.10.2013
comment
Зачем вам это делать, если Qt изначально поддерживает отправку данных через сокеты TCP/IP? Установить соединение и отправить простое сообщение очень просто.   -  person Kuba hasn't forgotten Monica    schedule 29.10.2013


Ответы (2)


Вы не можете использовать команду канала (|) с QProcess таким образом.

Есть несколько способов справиться с этим: -

Вы можете вызвать первую команду и получить ее вывод перед обработкой либо в Qt, либо с помощью другого вызова QProcess.

Или создайте сценарий, который вы вызываете из QProcess, и получите результат.

Наконец, если вы используете linux/OSX, вы можете вызвать QProcess с помощью /bin/bash и передать ему команду. Например: -

env = "/bin/bash \"echo TRIG | nc 192.168.1.100 23 -q1\"";
process1.execute(env);

Вы, вероятно, можете найти эквивалент /bin/bash для Windows, возможно, cmd.exe

person TheDarkKnight    schedule 29.10.2013
comment
Спасибо за подсказку. Однако он возвращает следующее: /bin/bash: echo TRIG | nc 192.168.1.100 23 -q1: Нет такого файла или каталога Вероятно, это что-то другое (путь?) - person user2655700; 29.10.2013
comment
Что такое TRIG, это скрипт или программа? Я не узнаю это как стандартный вызов bash. - person TheDarkKnight; 29.10.2013
comment
TRIG — это просто команда SCPI, которая запускает сбор данных на моем удаленном устройстве. - person user2655700; 29.10.2013
comment
Можно ли использовать полный путь к команде? Я предполагаю, что путь среды не настроен, и в этом случае, в качестве альтернативы, вы можете установить среду процесса перед вызовом exec. - person TheDarkKnight; 29.10.2013
comment
Мне кажется, что эхо - это проблема. Если я попытаюсь использовать только env = /bin/bash\echo abc\, он вернет ту же ошибку. Может быть, я не понимаю синтаксис /bin/bash. Команда TRIG является командой SCPI и не имеет полного пути. Я думаю, что использую это правильно. Я попробую два других ваших предложения, если это не сработает (но оно самое удобное). - person user2655700; 29.10.2013
comment
Когда я сказал настроить среду, я имел в виду вызов функции QProcess setProcessEnviroment, а не передачу ее в команде QProcess. Вот так: QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - person TheDarkKnight; 29.10.2013

В приведенном ниже коде показана довольно полная асинхронная реализация этой функциональности. Он демонстрирует, как это можно сделать без запуска внешних процессов и как использовать лямбда-выражения C++11 в Qt 5. Для Qt 4 слоты из main() должны жить в своем собственном классе, производном от QObject.

скриншот

#include <QtWidgets>
#include <QtNetwork>

class SocketSignaler : public QObject
{
   Q_OBJECT
   Q_SLOT void stateChanged(QAbstractSocket::SocketState state) {
      if (state == QAbstractSocket::UnconnectedState) emit unconnected();
      else emit busy();
      emit hasState(this->state());
   }
public:
   explicit SocketSignaler(QAbstractSocket * socket) : QObject(socket) {
      connect(socket, &QAbstractSocket::stateChanged, this, &SocketSignaler::stateChanged);
      connect(&(const QObject&)QObject(), &QObject::destroyed, this, // defer signal emission
              [=]{ emit stateChanged(socket->state()); }, Qt::QueuedConnection);
   }
   Q_SIGNAL void busy();
   Q_SIGNAL void unconnected();
   Q_SIGNAL void hasState(const QString &);
   QString state() const {
      switch (static_cast<QAbstractSocket*>(parent())->state()) {
      case QAbstractSocket::UnconnectedState: return "Disconnected";
      case QAbstractSocket::HostLookupState: return "Looking up host";
      case QAbstractSocket::ConnectingState: return "Connecting";
      case QAbstractSocket::ConnectedState: return "Connected";
      case QAbstractSocket::ClosingState: return "Closing";
      default: return {};
      }
   }
};

class Ui : public QWidget {
   Q_OBJECT
   Q_PROPERTY(bool busy WRITE setBusy)
   QVBoxLayout m_layout{this};
   QFormLayout m_form;
   QLineEdit m_target{"192.168.1.100"};
   QLineEdit m_message{"TRIG"};
   QLabel m_state;
   QDialogButtonBox m_box;
   QPushButton * const m_send = m_box.addButton("Send", QDialogButtonBox::AcceptRole);
   QPushButton * const m_cancel = m_box.addButton(QDialogButtonBox::Cancel);
   QMessageBox m_msgBox{this};
public:
   Ui() {
      m_form.addRow("Target Host", &m_target);
      m_form.addRow("Command", &m_message);
      m_layout.addLayout(&m_form);
      m_layout.addWidget(&m_state);
      m_layout.addWidget(&m_box);
      m_msgBox.setIcon(QMessageBox::Critical);
      connect(m_send, &QPushButton::clicked, this, &Ui::send);
      connect(m_cancel, &QPushButton::clicked, this, &Ui::cancel);
   }
   void setState(const QString & text) { m_state.setText(text); }
   QString target() const { return m_target.text(); }
   QString message() const { return m_message.text(); }
   void showError(const QString & text) {
      m_msgBox.setText(text);
      m_msgBox.show();
   }
   void setBusy(bool busy) {
      m_send->setEnabled(!busy);
      m_cancel->setEnabled(busy);
   }
   Q_SIGNAL void send();
   Q_SIGNAL void cancel();
};

int main(int argc, char *argv[])
{
   const int targetPort = 23;
   QApplication app{argc, argv};
   Ui ui;
   ui.show();

   QTcpSocket socket;
   SocketSignaler socketSig{&socket};
   QObject::connect(&socketSig, &SocketSignaler::hasState, &ui, &Ui::setState);

   QStateMachine machine;
   QState sReady{&machine};
   QState sBusy{&machine};
   sReady.assignProperty(&ui, "busy", false);
   sBusy.assignProperty(&ui, "busy", true);
   sReady.addTransition(&socketSig, &SocketSignaler::busy, &sBusy);
   sBusy.addTransition(&socketSig, &SocketSignaler::unconnected, &sReady);

   QObject::connect(&ui, &Ui::send, [&](){
      socket.connectToHost(ui.target(), targetPort);
   });
   QObject::connect(&ui, &Ui::cancel, [&](){ socket.abort(); });
   QObject::connect(&socket,
                    static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>
                    (&QAbstractSocket::error), [&]()
   {
      ui.showError(socket.errorString());
   });
   QObject::connect(&socket, &QAbstractSocket::connected, [&](){
      auto msg = ui.message().toLatin1();
      msg.append('\n');
      if (socket.write(msg) >= msg.size()) socket.close();
   });
   QObject::connect(&socket, &QAbstractSocket::bytesWritten, [&](){
      if (!socket.bytesToWrite()) socket.close();
   });

   machine.setInitialState(&sReady);
   machine.start();
   return app.exec();
}
#include "main.moc"
person Kuba hasn't forgotten Monica    schedule 29.10.2013