LINUX.ORG.RU

Захват stdout'а какой-либо программы в своей программе (СИ)

 


0

2

Здравствуйте.

Я хочу в своей программе запускать другую программу и ловить то, что она выдаёт в stdout.

Допустим делаю это так:

#include <stdio.h>

int main()
 {
   FILE * som_prog;
   char stroka[200];

   som_prog = popen("top", "r");

   while (!feof(som_prog))
    {
      fgets(stroka, 199, som_prog);
      printf("START: %s", stroka);
    }

   pclose(som_prog);
   printf("END\n");
   return 0;
 }

// gcc -Wall -Wextra as2.c -o as2

В данном случае запускаю «top» и получаю ожидаемое...

...
START:  9481 dima      20   0  617380  61688  49960 S   6,0  0,8  59:14.48 gnome-system-mo                                           
START:  2915 dima      20   0 1115668 196464  57604 S   2,3  2,4  73:16.01 plugin-containe                                           
START:  1417 root      20   0  358360 112796  88736 S   1,0  1,4  66:37.20 Xorg                                                      
START:  2501 dima      20   0 1514860 190560  71068 S   1,0  2,3  33:44.33 compiz                                                    
START:  5991 dima      20   0  656628  32728  23936 S   1,0  0,4   0:17.11 gnome-terminal 
...
...то есть всё хорошо.

Однако заковыка в другом. Мне нужно ловить данные от программы, которая сначала «плюёт» пару строк (и они успешно ловятся), а потом эта программа создаёт ещё один свой поток и «плюёт» строки уже из него. И вот эти строки уже не ловятся.

Что можно придумать?

★

которая сначала «плюёт» пару строк (и они успешно ловятся), а потом эта программа создаёт ещё один свой поток и «плюёт» строки уже из него

Что-то я не распарсил, объясни нормально. В той программе создается еще один поток через pthread? Или делается форк?

hippi90 ★★★★★
()

Если пускать через dup2+fork+execve, то дескрипторы наследуются потомками потомков и тд.

anonymous
()
Ответ на: комментарий от hippi90

В той программе создается еще один поток через pthread? Или делается форк?

Я честно говоря точно не знаю, что происходит в той проге. Она написана на с++ (я в нём не смыслю) с использованием библиотеки «boost». Вообще это майнер (nheqminer), и я хочу ловить то, что он выдаёт.

Вот кусок его main.cpp:

#ifdef _MSC_VER
    init_logging(boost::log::core::get(), log_level);
#else
    std::cout << "Setting log level to " << log_level << std::endl;
    boost::log::add_console_log(
        std::clog,
        boost::log::keywords::auto_flush = true,
        boost::log::keywords::filter = boost::log::trivial::severity >= log_level,
        boost::log::keywords::format = (
        boost::log::expressions::stream
            << "[" << boost::log::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp", "%H:%M:%S")
            << "][" << boost::log::expressions::attr<boost::log::attributes::current_thread_id::value_type>("ThreadID")
            << "] "  << boost::log::expressions::smessage
        )
    );
    boost::log::core::get()->add_global_attribute("TimeStamp", boost::log::attributes::local_clock());
    boost::log::core::get()->add_global_attribute("ThreadID", boost::log::attributes::current_thread_id());
#endif

Получается так: я ловлю вот эту строку - «Setting log level to », а дальше идут эти строки - «TimeStamp», «ThreadID» и т.д., но они уже не ловятся.

stD ★
() автор топика
Ответ на: комментарий от stD

Указанные выше строки кода не выводят ничего в лог, а задают формат последующих записей.

Кроме того, clog пишет в stderr, а ты перехватываешь stdout.

vzzo ★★★
()
Ответ на: комментарий от vzzo

Вот ещё кусок кода той программы:

int c = 0;
while (sc.isRunning()) {
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
  if (++c % 1000 == 0)
    {
	double allshares = speed.GetShareSpeed() * 60;
	double accepted = speed.GetShareOKSpeed() * 60;
	BOOST_LOG_TRIVIAL(info) << CL_YLW "Speed [" << INTERVAL_SECONDS << " sec]: " << 
	speed.GetHashSpeed() << " H/s, " <<
	speed.GetSolutionSpeed() << " Sol/s" << 
	CL_N;
    }

  if (api) while (api->poll()) { }
}

В терминале это выглядит так:

...
[21:50:47][0x00007ff176828700] stratum | Reconnecting in 3 seconds...
[21:50:49][0x00007ff17831b780] Speed [300 sec]: 0 H/s, 0 Sol/s
[21:50:50][0x00007ff176828700] stratum | Connecting to stratum server ze.suprnova.cc:2142
[21:50:50][0x00007ff176828700] stratum | resolve: Host not found (authoritative)
...

Как мне это изловить? )

stD ★
() автор топика

popen не умеет в перехват stderr, только stdout.

Тебе надо в своей программе создать пайпы через pipe(), форкнуться, заменить стандартные потоки на пайпы с помощью dup2(), и сделать execv() с новой программой. Примерно как тут http://www.cs.loyola.edu/~jglenn/702/S2005/Examples/dup2.html

hippi90 ★★★★★
()
Ответ на: комментарий от hippi90

popen не умеет в перехват stderr, только stdout.

Дык ведь это не ошибки, это нормальная работа проги. Почему нужно перехватывать stderr? Объясните пожалуйста.

...

Какой из примеров (по Вашей ссылке) взять за основу?

stD ★
() автор топика
Ответ на: комментарий от stD

Перехватывать stderr нужно потому, что твой майнер в него пишет.

legolegs ★★★★★
()
Ответ на: комментарий от shdown

popen(«my-cool-program 2>&1», «r»)

Это работает! Спасибо!

stD ★
() автор топика
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.