LINUX.ORG.RU

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

 


0

1

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

Я уже задавал подобный вопрос, ответ на него вроде бы прост:

#include <stdio.h>

int main() 
{
	FILE *in;
	char buff[512];

	if(!(in = popen("df -h", "r")))
         {
		printf("xana");
	 }

	while(fgets(buff, sizeof(buff), in)!=NULL)
         {
		printf("RECIV:%s", buff);
	 }

	pclose(in);
    return 0;
}

Получаю всё как положено.

RECIV:Файл.система   Размер Использовано  Дост Использовано% Cмонтировано в
RECIV:udev             3,9G         4,0K  3,9G            1% /dev
RECIV:tmpfs            799M         1,4M  798M            1% /run
RECIV:/dev/sdb1        143G         105G   31G           78% /
RECIV:none             4,0K            0  4,0K            0% /sys/fs/cgroup
RECIV:none             5,0M            0  5,0M            0% /run/lock
RECIV:none             3,9G          28M  3,9G            1% /run/shm
RECIV:none             100M          52K  100M            1% /run/user

Программа которую я планирую запускать (это майнер EWBF) подключается к пулу (передавая ему пароль) и начинает майнить.

Дык вот в чём дело: если запустить майнер с НЕ правильным паролем, то он выдаёт сообщение об ошибке, а моя программа ловит его и завершает работу.

RECIV:+-------------------------------------------------+
RECIV:|         EWBF's Zcash CUDA miner. 0.3.4b         |
RECIV:+-------------------------------------------------+
RECIV:INFO: Current pool: zec.suprnova.cc:2142
RECIV:INFO: Selected pools: 1
RECIV:INFO: Solver: Auto.
RECIV:INFO: Devices: All.
RECIV:INFO: Temperature limit: 90
RECIV:INFO: Api: Disabled
RECIV:---------------------------------------------------
RECIV:INFO: Target: 003c3c3c3c3c3c3c...
RECIV:INFO: Detected new work: 4902
RECIV:ERROR: Stratum authorization error

Если же запустить с правильными данными, то моя программа ничего не ловит, как будто майнер ничего не выдаёт (а он выдаёт).

То есть (как я думаю) когда майнер запускается с правильными данными, то внутри что-то форкается и инфа выдаётся неизвестно куда. (другого объяснения я не занаю)

Такое может быть? Или почему вобще так происходит?

П.С. Извиняюсь за формулировку вопроса и заранее спасибо.



Последнее исправление: stD (всего исправлений: 1)

Код ответа можешь узнать с помощью wait или waitpid. Можешь миспользовать pipe(). А так да, у тебя может быть не тот поток вывода.

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

./prog >stdout.log 2>stderr.log

./miner >stdout.log 2>stderr.log 

Файлы пустые.

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

Запусти майнер так и ps посмотри.

dima@starik:~$ ps ax | grep miner
 8801 pts/3    Sl+    0:02 /home/dima/miner_nvid_suprnov/miner 
 8812 pts/1    S+     0:00 grep --color=auto miner
dima@starik:~$ 

Хм, процесс один. Что же тогда происходит?

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

Это буферизация.

stdio майнера видит, что stdout не соединён с TTY, и включает буферизацию по 4096 байт (или около того), а не по строке. Бороться с этим сложно (можно попытаться подгрузить при помощи LD_PRELOAD специальную библиотеку, которая сделает setvbuf и уберёт буферизацию).

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

Выруби буферизацию чтения из потока

Попробовал без буферизации - setvbuf(in, 0, _IONBF, 0);

и с буфером 5Кб - setvbuf(in, buffer, _IOLBF, 5000);

Результат отрицательный.

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

Для gdb <экзешник>

GDB останавливается на строке «while(fgets(buff, sizeof(buff), in)!=NULL)»

(gdb) start
Temporary breakpoint 1 at 0x4006c9: file minerNHEQMINER2.c, line 4.
Starting program: /home/dima/minerNHEQMINER 

Temporary breakpoint 1, main () at minerNHEQMINER2.c:4
4	{
(gdb) n
9	if(!(in = popen("/home/dima/miner_nvid_suprnov/miner 
(gdb) n
14	    setvbuf(in, buffer, _IOLBF, 5000);
(gdb) n
15		while(fgets(buff, sizeof(buff), in)!=NULL)
(gdb) n

И с буфером и без.

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

А может, у него из-за буфера задержки больше, чем он готов терпеть?

Что Вы имеете ввиду?

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

stdio майнера видит, что stdout не соединён с TTY,

Похоже на мою ситуацию, а как его соединить с чем-нибудь?))

специальную библиотеку,

А что за специальная библиотека?

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

Это могли сделать, чтобы если майнер запускает система из инициализации, он не мусорил в терминал

Разумно, а fread поожет в этом случае? Впрочем сейчас попробую.

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

Вот ключи майнера:

--help, -h          Show this help.
--server            Stratum server only hostname or ip address.
--port              Stratum server port.
--user              Stratum user.
--pass              Stratum password.
--fee               The developer fee in percent allowed decimals for example 0, 1, 2.5, 1.5 etc.
--pec               Power efficiency calculator. Shows power statistics.
--cuda_devices      Space-separated list of cuda devices.
                    Without this option all devices are used.
--solver            Disable benchmark and use specified solver
                    Allowed values from 0 to 3.
--eexit             Exit in case of error. Value 1 exit if miner cannot restart workers.
                    Value 2 if lost connection with the pool. 3 both cases.
--log               Create file miner.log in directory of miner.
                    Allowed values 1 and 2. 1 only errors, 2 will repeat console output.
--logfile           Set custom filename.
--config            Config file.
--tempunits         Temperature units, allowed values: C for celsius, F for fahrenheit and K for kelvin :)).
--templimit         Temperature limit, gpu will be stopped if this limit is reached.
--api               Enable api without an argument will be listen on 127.0.0.1:42000,
                    You can set listen address as an argument for example: --api 0.0.0.0:12345
                    Allowed ports 1000 - 65535

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

Чем не устраивает?

Да я думал о нём, только хотелось попроще сделать.

Там строки однообразные, как их разделять непонятно...

Total speed: 0 Sol/s
CUDA: Device: 0 Selected solver: 4
INFO 22:16:48: GPU0 Accepted share 52ms [A:1, R:0]
Temp: GPU0 56C 
GPU0: 24 Sol/s 
Total speed: 24 Sol/s
INFO 22:17:17: GPU0 Accepted share 53ms [A:2, R:0]
Temp: GPU0 58C 
GPU0: 20 Sol/s 
Total speed: 20 Sol/s
Temp: GPU0 60C 
GPU0: 19 Sol/s 
Total speed: 19 Sol/s
INFO: Target: 00a8a8a8a84e1c5d...
INFO: Detected new work: 4961
Temp: GPU0 61C 
GPU0: 19 Sol/s 
Total speed: 19 Sol/s
INFO 22:18:54: GPU0 Accepted share 52ms [A:3, R:0]
Temp: GPU0 61C 
GPU0: 19 Sol/s 
Total speed: 19 Sol/s
INFO 22:18:56: GPU0 Accepted share 52ms [A:4, R:0]

Если только по времени.

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

Можешь указать в качестве файла пайп или читать обычный файл tail -f.

Спасибо, много вариантов, буду думать и пробовать разные.

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

Там строки однообразные, как их разделять непонятно...

Awk, cut, grep. Выбирай

watashinoshi
()

конечно не С, но откройте для себя expect

MKuznetsov ★★★★★
()

Тут вам много чего написали, в том числе и про expect, но если хочется чего-то странного, то можно и на Си написать код, который будет создавать псевдотерминал и запускать программу-потомка так, что она будет считать, что выполняется в терминале. http://rachid.koucha.free.fr/tech_corner/pty_pdip.html

mky ★★★★★
()
Ответ на: комментарий от stD
dima@starik:~$ ps ax | grep miner
 8801 pts/3    Sl+    0:02 /home/dima/miner_nvid_suprnov/miner 
 8812 pts/1    S+     0:00 grep --color=auto miner
dima@starik:~$ 

Хм, процесс один. Что же тогда происходит?

А вы не видите, что miner работает с новым псевдотерминалом, чем grep? Все советы, данные тут совершенно бесполезны.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Обнаружилось такое явление. Если запустить прогу и подождать минуты четыре, то прилетает пачка данных, около 5Кб. Ещё через четыре минуты снова пачка данных того же размера (около 5Кб) и т.д.

Как будто данные в каком-то буфере копятся, а потом вываливаются.

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

Это так и должно быть, буфер PIPE_SIZE 4096 байт. Но вы говорите загадками, то что прилетает - это то что вы хотите или какая-то другая инфа?

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

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

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

Вот кусок того что выдаёт:

...
RECIV:_85_3432_Temp: GPU0: 61C 
RECIV:_86_3457_GPU0: 20 Sol/s 
RECIV:_87_3488_Total speed: 20 Sol/s
RECIV:_88_3530_+-----+-------------+--------------+
RECIV:_89_3567_| GPU | Power usage |  Efficiency  |
RECIV:_90_3604_+-----+-------------+--------------+
RECIV:_91_3641_|  0  |      0W     |  0.00 Sol/W  |
RECIV:_92_3682_+-----+-------------+--------------+
RECIV:_93_3720_INFO: Detected new work: 14c
RECIV:_94_3781_INFO 18:55:39: GPU0 Accepted share 64ms [A:10, R:0]
RECIV:_95_3842_INFO 18:55:49: GPU0 Accepted share 63ms [A:11, R:0]
RECIV:_96_3886_Temp: GPU0: 62C 
RECIV:_97_3911_GPU0: 20 Sol/s 
RECIV:_98_3942_Total speed: 20 Sol/s
RECIV:_99_3984_+-----+-------------+--------------+
RECIV:_100_4021_| GPU | Power usage |  Efficiency  |
RECIV:_101_4058_+-----+-------------+--------------+
RECIV:_102_4095_|  0  |      0W     |  0.00 Sol/W  |
^C
dima@starik:~$ 

Я приделал подсчёт строк (первая цифра) и кол-во принятых символов (вторая цифра).

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

Тогда вышеуказанные советы насчёт запуска под эмуляцией терминала подойдут. Вы точно тот вывод ps не скомпилировали не из нескольких (в том числе одновременных исполняемых miner-ов)? В принципе это можно объяснить, что процесс меняет терминал только при уже работе на терминале, но что он этим хочет добиться - не понятно и смысла нет.

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

Вы точно тот вывод ps не скомпилировали не из нескольких

Запустил один майнер в терминале и всё, а в другом сделал ps ax.

Подскажите что делать?

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