Linux C : не удается запустить «nmcli dev list iface», если вы не вошли в систему

#c #linux #network-programming #popen

#c #linux #сетевое программирование #popen

Вопрос:

У меня есть приложение, написанное на Qt C , которое должно собирать информацию о сетевом подключении. Код для этого показан ниже:

 class NetworkHelper {
public:
  static void networkInfo(const QString amp;device, QString amp;hwaddr, QString amp;hwdesc,    QString amp;ip, QString amp;ipmask, QString amp;gateway, QString amp;dhcp)
{
  FILE *fp;
  char buf[512];
  QRegularExpression re_vendor("GENERAL.VENDOR:\s (?<vendor>. )");
  QRegularExpression re_product("GENERAL.PRODUCT:\s (?<product>. )");
  QRegularExpression re_hwaddr("GENERAL.HWADDR:\s (?<hwaddr>. )");
  QRegularExpression re_ip_gateway("ip = (?<ip>\d .\d .\d .\d )/\d , gw = (?<gateway>\d .\d .\d .\d )");
  QRegularExpression re_ipmask("subnet_mask = (?<ipmask>\d .\d .\d .\d )");
  QRegularExpression re_dhcp("dhcp_server_identifier = (?<dhcp>\d .\d .\d .\d )");
  QRegularExpressionMatch match;

  hwaddr = QString();
  hwdesc = QString();
  ip = QString();
  ipmask = QString();
  gateway = QString();
  dhcp = QString();

#ifdef Q_OS_LINUX
  const char *cmd = QString("nmcli dev list iface %1").arg(device).toUtf8().constData();

  if (!(fp = popen(cmd,"r")))
    return;

  while (fgets(buf, sizeof(buf), fp) != NULL)
  {
    match = re_ip_gateway.match(buf);
    if (match.hasMatch())
    {
      ip = match.captured("ip");
      gateway = match.captured("gateway");
    }
    match = re_ipmask.match(buf);
    if (match.hasMatch())
      ipmask = match.captured("ipmask");
    match = re_dhcp.match(buf);
    if (match.hasMatch())
      dhcp = match.captured("dhcp");
    match = re_vendor.match(buf);
    if (match.hasMatch())
      hwdesc = match.captured("vendor");
    match = re_product.match(buf);
    if (match.hasMatch())
      hwdesc  = hwdesc.isEmpty() ? match.captured("product") : " / " match.captured("product");
     match = re_hwaddr.match(buf);
     if (match.hasMatch())
       hwaddr = match.captured("hwaddr");
  }
  ret = pclose(fp);  
#endif
}
};
  

Приложение запускается как автозапуск сразу после загрузки компьютера. Проблема в том, что popen() возвращает код 139, что, насколько я понимаю, означает segfault, а цикл while не выполняется, поэтому я не могу получить информацию о сети.

Если я вхожу в систему и вручную запускаю приложение, приведенный выше код выполняется нормально, и я получаю всю необходимую сетевую информацию.

Кроме того, другая часть приложения запускает HTTP-сервер, к которому я могу подключиться и при автозапуске приложения, поэтому, похоже, проблем с сетью нет.

Кто-нибудь знает, как я смогу запустить popen () при автозапуске приложения?

Комментарии:

1. NetworkManager не всегда запускается непосредственно во время загрузки. Есть ли у вас обязательное условие для подключения к сети в вашем сценарии автозапуска?

2. Нет, я этого не делаю. Так в этом может быть проблема? Я использую Ubuntu. Есть ли у вас дополнительная информация о том, что мне понадобится в моем сценарии?

3. Я попытался добавить ‘sudo service network-manager start’ в свой сценарий автозапуска, но в этом случае мой http-сервер не запускается, и, следовательно, я вообще не могу подключиться к приложению. Есть идеи, как мне поступить?

4. Может кто-нибудь, пожалуйста, дать подсказку, что мне нужно добавить в мой сценарий austostart, чтобы гарантировать, что NetworkManager запущен?

5. просто для ясности. Если мое приложение работает в фоновом режиме, и я вхожу в компьютер или выполняю ssh, то popen («nmcli dev list iface eth0», «r») работает нормально и выдает код возврата 0. Если я выхожу из системы или завершаю сеанс ssh, то команда popen() не работает и выдает код возврата 139.

Ответ №1:

Обнаружил, что мое приложение запустилось раньше сетевого менеджера (или что-то в этом роде — не совсем уверен, почему я увидел вышеупомянутое поведение, поскольку я смог подключиться к http-серверу, запущенному приложением, но не смог запустить команду nmcli).

В моем сценарии автозапуска я добавил условие не запускать приложение до установления подключения к Интернету, что решило мою проблему