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 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.