Как сделать так, чтоб дочерний процесс делал вывод в родительский?Например я создаю поток для запуска комманды "ps aux" (не суть важно какая комманда) и хочу, чтоб она сделала вывод в родительский процесс.. Например построчно прочитать, то что она ответит.
Единственное, что приходит на ум - это использовать pipe, но возможно есть "более другие" способы.. Или скажем более правильные? Просветите тёмного.. Или я пытаюсь всё усложнить? :)
>Как сделать так, чтоб дочерний процесс делал вывод в родительский?
>
>Например я создаю поток для запуска комманды "ps aux" (не суть важно
>какая комманда) и хочу, чтоб она сделала вывод в родительский процесс..
>Например построчно прочитать, то что она ответит.Мне кажется здесь более правильно использовать popen.
>
>Единственное, что приходит на ум - это использовать pipe, но возможно есть
>"более другие" способы.. Или скажем более правильные? Просветите тёмного.. Или я
>пытаюсь всё усложнить? :)
>>Как сделать так, чтоб дочерний процесс делал вывод в родительский?я попытался сделать так , но чего-то не работает, погляди ты
кусок кодаbuffer=(char *)malloc(buffer_len);
if(buffer==NULL)
{
printf("\n Error cann't allocate memory for buffer");
exit(1);
}
bzero(buffer,buffer_len);
dump=popen(dump_com,"r");
if(dump==NULL)
{
printf("\n Error cann't open dump");
exit(1);
}
/*fgets(buffer,buffer_len,dump); аналогичный результат*/
fscanf(dump,"%s",buffer);
printf("string=%s\nsize=%d",buffer,(int)strlen(buffer));
>>>Как сделать так, чтоб дочерний процесс делал вывод в родительский?
>
>я попытался сделать так , но чего-то не работает, погляди ты
>кусок кода
>
>buffer=(char *)malloc(buffer_len);
>if(buffer==NULL)
>{
> printf("\n Error cann't allocate memory for buffer");
> exit(1);
>}
>bzero(buffer,buffer_len);
>dump=popen(dump_com,"r");
>if(dump==NULL)
>{
> printf("\n Error cann't open dump");
> exit(1);
>}
>/*fgets(buffer,buffer_len,dump); аналогичный результат*/
>fscanf(dump,"%s",buffer);
>printf("string=%s\nsize=%d",buffer,(int)strlen(buffer));
Да вроде все правильно. У меня работает (Linux)://==============================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>main() {
FILE *dump;
int buffer_len=1024;
char *buffer;
char *dump_com;dump_com=strdup("ls -l");
buffer=(char *)malloc(buffer_len);
if(buffer==NULL) {
perror("malloc");
exit(1);
}
bzero(buffer,buffer_len);
dump=popen(dump_com,"r");
if(dump==NULL)
{
perror("dump");
printf("\n Error cann't open dump");
exit(1);
}
while (fgets(buffer,buffer_len-1,dump)) {
printf("size=%d,string=%s",strlen(buffer),buffer);
}
pclose(dump);
}
//============================================Какие ошибки-то выдает?
>Да вроде все правильно. У меня работает (Linux):
>
>Какие ошибки-то выдает?Не помню в чем дело было, но теперь и у меня работает тоже (FreeBSD).
Вопрос вот какой появился, если родительская программа завершается, а дочерний процесс (т.е. тот который на другом конце канала, который мы порождаем) все еще крутится, то вызов функции pclose(...) не завершает выполнение дочернего процесса.Т.е. надо бы как-то его придавить процесс то этот.
> Вопрос вот какой появился, если родительская программа завершается,
>а дочерний процесс (т.е. тот который на другом конце канала, который
>мы порождаем) все еще крутится, то вызов функции pclose(...) не завершает
>выполнение дочернего процесса.
>
>Т.е. надо бы как-то его придавить процесс то этот.Вообще то, насколько я знаю, pclose ожидает завершения child процесса, поэтому по идее parent не должен завершится до окончания вызова pclose, т.е. раньше чем child. Ну а вообще, если надо "прибить" всех детей, то перед выходом, вместо pclose, можно выполнить kill(0,9) - тогда погибнут все, включая папашу. Но мне кажется лучше использовать pipe+dup2+fork, тогда мы будем знать какой pid имеет child и в случае необходимости слать сигнал конкретному pid. Хотя возможно есть какой-нибудь способ получения pid процесса запущенного popen, но мне он неизвестен.
А у меня от такая проблема:
Хочу вести диалог с дочерним процессом, тоесть давать ему комманду, а он мне ответ. Работаю с Mysql.#include <stdio.h>
#include <stdlib.h>
#include <strins.h>void main()
{
FILE *dump;
char buffer, *dump_coml;dump_com=("/usr/local/mysql/bin/mysq -u user --password=password --database=mydb");
dump=popen(dump_com,"r+");
if (dump==NULL)
{
perror("dump");
printf("Error in pipe creation");
exit(1);
}
fprintf(dump,"select * from users;\n");while (!feof(dump))
{
fscanf(dump,"%c",&buffer);
printf("%c",buffer);
}
pclose(dump);
exit(0);
}Если комманду SQL давать с ключём --exec=="select * from users"
то всё работает. Что я не правильно сделал? Или это как-то по другому делается? Проблема в том, что программа замирает и вроде как чего-то ждёт, но чего не понятно.. Может я ей команду методом printf не так посылаю? :(
>А у меня от такая проблема:
>Хочу вести диалог с дочерним процессом, тоесть давать ему комманду, а он
>мне ответ. Работаю с Mysql.
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <strins.h>
>
>void main()
>{
> FILE *dump;
> char buffer, *dump_coml;
>
> dump_com=("/usr/local/mysql/bin/mysq -u user --password=password --database=mydb");
>
> dump=popen(dump_com,"r+");
> if (dump==NULL)
> {
> perror("dump");
> printf("Error in pipe creation");
> exit(1);
> }
>
> fprintf(dump,"select * from users;\n");
>
> while (!feof(dump))
> {
> fscanf(dump,"%c",&buffer);
> printf("%c",buffer);
> }
> pclose(dump);
> exit(0);
>}
>
>Если комманду SQL давать с ключём --exec=="select * from users"
>то всё работает. Что я не правильно сделал? Или это как-то по
>другому делается? Проблема в том, что программа замирает и вроде как
>чего-то ждёт, но чего не понятно.. Может я ей команду методом
>printf не так посылаю? :(
Слыш чел, сори что тут ка-то не в мазу влезаю, хош дам инфу как это на пхп сделать, без заморочек ? Тоже процесс открыть ?! Или вызывай код пхп-шный, как вариант пойдёт ?! Я демон пишу на пхп, он кучу всего делает. Думаю понимаешь чем удобен пхп, особенно вушкции с локальными переменными.
>Слыш чел, сори что тут ка-то не в мазу влезаю, хош дам
>инфу как это на пхп сделать, без заморочек ? Тоже процесс
>открыть ?! Или вызывай код пхп-шный, как вариант пойдёт ?! Я
>демон пишу на пхп, он кучу всего делает. Думаю понимаешь чем
>удобен пхп, особенно вушкции с локальными переменными.
На ПХП я см могу, мне на сях это надо...
>А у меня от такая проблема:
>Хочу вести диалог с дочерним процессом, тоесть давать ему комманду, а он
>мне ответ. Работаю с Mysql.
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <strins.h>
>
>void main()
>{
> FILE *dump;
> char buffer, *dump_coml;
>
> dump_com=("/usr/local/mysql/bin/mysq -u user --password=password --database=mydb");
>
> dump=popen(dump_com,"r+");
> if (dump==NULL)
> {
> perror("dump");
> printf("Error in pipe creation");
> exit(1);
> }
>
> fprintf(dump,"select * from users;\n");
>
> while (!feof(dump))
> {
> fscanf(dump,"%c",&buffer);
> printf("%c",buffer);
> }
> pclose(dump);
> exit(0);
>}
>
>Если комманду SQL давать с ключём --exec=="select * from users"
>то всё работает. Что я не правильно сделал? Или это как-то по
>другому делается? Проблема в том, что программа замирает и вроде как
>чего-то ждёт, но чего не понятно.. Может я ей команду методом
>printf не так посылаю? :(Из man popen:
Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.Вывод первый: читать man pages полезно.
Вывод второй: проверять код возврата (в данном случае, fprintf) _очень_ полезно.
Вывод третий: боюсь, что для двухстороннего разговора вам без явных fork/pipe/dup/exec не обойтись...
Вот то что мне нужно было:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void popen_err()
{
perror("dump");
printf("\n Error can't open pipe!");
exit(1);}
int main()
{
FILE *dump,*dump2;
char *buf, buf2, *tmp, *dump_com, *dump_com2;
dump_com=strdup("/usr/local/mysql/bin/mysql -u user --password=pass --database=control --execute='select id from users'");
dump_com2=strdup("/sbin/ipfw -a l 300");buf=(char *)malloc(1024);
dump=popen(dump_com,"r");
if (dump==NULL) popen_err();
fscanf(dump,"%s",buf);
while (!feof(dump))
{
fscanf(dump,"%s",buf);
if (feof(dump)) break;
tmp=strdup(dump_com2);
strcat(tmp,buf);
dump2=popen(tmp,"r");
if (dump2==NULL) popen_err;
while(!feof(dump2))
{
fscanf(dump2,"%c",&buf2);
printf("%c",buf2);
}
pclose(dump2);
}
pclose(dump);
exit(0);
}Смысл таков, на основе выбраных id из базы которые переделываются в номера правил в ipfw, вывести на экран показания по этим правилам.
Вообще конечная идея писать в другую базу показания счётчиков байт, но это дополнительный popen и вытаскивание инфы из строки. По мне, так то, что я написал - криво! Как можно это упростить и привести к нормальному коду? Может такие вещи вообще по другому делаются?
>Вот то что мне нужно было:
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>
>void popen_err()
>{
> perror("dump");
> printf("\n Error can't open pipe!");
> exit(1);
>
>}
>
>int main()
>{
> FILE *dump,*dump2;
> char *buf, buf2, *tmp, *dump_com, *dump_com2;
>
> dump_com=strdup("/usr/local/mysql/bin/mysql -u user --password=pass --database=control --execute='select id from users'");
> dump_com2=strdup("/sbin/ipfw -a l 300");
>
> buf=(char *)malloc(1024);
>
> dump=popen(dump_com,"r");
> if (dump==NULL) popen_err();
> fscanf(dump,"%s",buf);
> while (!feof(dump))
> {
> fscanf(dump,"%s",buf);
> if (feof(dump)) break;
> tmp=strdup(dump_com2);
> strcat(tmp,buf);
> dump2=popen(tmp,"r");
> if (dump2==NULL) popen_err;
> while(!feof(dump2))
> {
> fscanf(dump2,"%c",&buf2);
> printf("%c",buf2);
> }
> pclose(dump2);
> }
>
> pclose(dump);
> exit(0);
>}
>Очень сложные вопросы вы задаете.
>Смысл таков, на основе выбраных id из базы которые переделываются в номера
>правил в ipfw, вывести на экран показания по этим правилам._Такое_ лучше, наверное, не на C писать, а на каком-нибудь bash/perl/etc (по вкусу).
>Вообще конечная идея писать в другую базу показания счётчиков байт, но это
>дополнительный popen и вытаскивание инфы из строки.Посмотрите в сторону ODBC; запуск шелла DB ради одного запроса выглядит ... ммм ... сомнительно. Да и у ipfw есть, насколько я понимаю, хорошо определенный интерфейс.
>По мне, так то,
>что я написал - криво! Как можно это упростить и привести
>к нормальному коду? Может такие вещи вообще по другому делаются?
>Очень сложные вопросы вы задаете.Зато жизненые.
>>Смысл таков, на основе выбраных id из базы которые переделываются в номера
>>правил в ipfw, вывести на экран показания по этим правилам.
>
>_Такое_ лучше, наверное, не на C писать, а на каком-нибудь bash/perl/etc (по
>вкусу).Ну я написал только кусок того, что должно выполнятся.. Вообще там данные будут не на экран выводится, а обрабатываться и заноситься в БД. Насколько я знаю, в шелле работа со строками не реализована. А в перле я не силён. :(
Делаются же подобные вещи как-то.
>Посмотрите в сторону ODBC; запуск шелла DB ради одного запроса выглядит ...
>ммм ... сомнительно. Да и у ipfw есть, насколько я понимаю,
>хорошо определенный интерфейс.Ну не одного запроса, а ради 1+<количество записей в выборке>. У ipfw хороший интерфейс, но мне нужен замер трафика каждый час на несколько правил и запсь в ДБ в таком виде, как мне это надо. Если это можно сделать проще, то как?
>>Очень сложные вопросы вы задаете.
>
>Зато жизненые.
>
>>>Смысл таков, на основе выбраных id из базы которые переделываются в номера
>>>правил в ipfw, вывести на экран показания по этим правилам.
>>
>>_Такое_ лучше, наверное, не на C писать, а на каком-нибудь bash/perl/etc (по
>>вкусу).
>
>Ну я написал только кусок того, что должно выполнятся.. Вообще там данные
>будут не на экран выводится, а обрабатываться и заноситься в БД.
>Насколько я знаю, в шелле работа со строками не реализована. А
>в перле я не силён. :(
>
>Делаются же подобные вещи как-то.
>
>>Посмотрите в сторону ODBC; запуск шелла DB ради одного запроса выглядит ...
>>ммм ... сомнительно. Да и у ipfw есть, насколько я понимаю,
>>хорошо определенный интерфейс.
>
>Ну не одного запроса, а ради 1+<количество записей в выборке>. У ipfw хороший интерфейс, но мне нужен замер трафика каждый час на несколько правил и запсь в ДБ в таком виде, как мне это надо. Если это можно сделать проще, то как?
Я может не совсем все правильно понял, но почему бы для записи в БД просто не использовать MySQL Api?
>Я может не совсем все правильно понял, но почему бы для записи
>в БД просто не использовать MySQL Api?
Спасибо за подсказку, это как раз то, что мне надо! :)Но всё же, не лдя всех програм есть свой апи, как тогда вести диалог с программой?
>>Я может не совсем все правильно понял, но почему бы для записи
>>в БД просто не использовать MySQL Api?
>Спасибо за подсказку, это как раз то, что мне надо! :)
>
>Но всё же, не лдя всех програм есть свой апи, как тогда
>вести диалог с программой?
Схема обычно такая (опять-таки, с точностью до проверок на ошибки):int pipe_parent_child[2];
int pipe_child_parent[2];pipe(pipe_parent_child);
pipe(pipe_child_parent);if(fork() == 0) {
dup2(pipe_parent_child[0], 0);
dup2(pipe_child_parent[1], 1);
close ненужные дескрипторы
execXX(whatever, ...);
} else {
Пишем в pipe_parent_child[1]
Читаем из pipe_child_parent[0]
}Это, собственно, все. Диавол, как всегда, в деталях. В эту схему легко ложатся простые фильтры (типа sed); а вот разбираться с выводом, предназначенным для человеческого глаза -- удовольствие ниже среднего.
>Я может не совсем все правильно понял, но почему бы для записи
>в БД просто не использовать MySQL Api?Кстати, что-то у меня mysql++ 1.7.9 не компилится.. :(
Выдаёт ошибку в makefile.
Дя него gcc 2.95.4 подойдёт?
Что кроме automke и autoconf ему надо? Там дока очень скудная по инсталляции..
>>>Посмотрите в сторону ODBC>Я может не совсем все правильно понял, но почему бы для записи
>в БД просто не использовать MySQL Api?А у MySQL API есть преимущества над ODBC? Я MySQL совсем не знаю.
>>>>Посмотрите в сторону ODBC
>
>>Я может не совсем все правильно понял, но почему бы для записи
>>в БД просто не использовать MySQL Api?
>
>А у MySQL API есть преимущества над ODBC? Я MySQL совсем не
>знаю.
С ODBC под юникса не сталкивался, зато в MYSQL API вник мгновенно, там просто созданы классы для работы с бд и через них ты работаешь, очень похоже на дельфийские компоненты, если всё делать кодом без дизайнера. :)Вот пример из мануала:
#include <iostream>
#include <iomanip>
#include <sqlplus.hh>
int main() {
Connection con("mysql_cpp_data");
// The full format for the Connection constructor is
// Connection(cchar *db, cchar *host="",
// cchar *user="", cchar *passwd="")
// You may need to specify some of them if the database is not on
// the local machine or you database username is not the same as your
// login name, etc..
Query query = con.query();
// This creates a query object that is bound to con.
query << "select * from stock";
// You can write to the query object like you would any other ostrem
Result res = query.store();
// Query::store() executes the query and returns the results
cout << "Query: " << query.preview() << endl;
// Query::preview() simply returns a string with the current query
// string in it.
cout << "Records Found: " << res.size() << endl << endl;
Row row;
cout.setf(ios::left);
cout << setw(17) << "Item"
<< setw(4) << "Num"
<< setw(7) << "Weight"
<< setw(7) << "Price"
<< "Date" << endl
<< endl;
Result::iterator i;
// The Result class has a read-only Random Access Iterator
for (i = res.begin(); i != res.end(); i++) {
row = *i;
cout << setw(17) << row[0]
<< setw(4) << row[1]
<< setw(7) << row["weight"]
// you can use either the index number or column name when
// retrieving the colume data as demonstrated above.
<< setw(7) << row[3]
<< row[4] << endl;
}
return 0;
}
Повторю вопрос:
Что-то у меня mysql++ 1.7.9 (MySQL API) не компилится.. :(
Выдаёт ошибку в makefile. Похоже он не правильно генерируется.
Дя него gcc 2.95.4 подойдёт?
Что кроме automke и autoconf ему надо? Там дока очень скудная по инсталляции..
>Повторю вопрос:
>Что-то у меня mysql++ 1.7.9 (MySQL API) не компилится.. :(
>Выдаёт ошибку в makefile. Похоже он не правильно генерируется.
>Дя него gcc 2.95.4 подойдёт?
>Что кроме automke и autoconf ему надо? Там дока очень скудная по
>инсталляции..
Если это на FreeBSD, то можно попробовать вызывать gmake вместо make.
Вообще-то ./configure обычно все как надо прописывает.
gmake - вообще не запускает ничего.autoconf пишет следующие варнинги:
automake: Makefile.am: required file `./INSTALL' not found
automake: Makefile.am: required file `./NEWS' not found
automake: Makefile.am: required file `./COPYING' not found
automake: Makefile.am: required file `./AUTHORS' not found
automake: Makefile.am: required file `./ChangeLog' not found
automake: configure.in: required file `./depcomp' not found
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/lang-compile.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/depend2.am: AMDEP does not appear in AM_CONDITIONAL
/usr/local/share/automake/am/lang-compile.am: AMDEP does not appear in AM_CONDITIONALautoconf проходит без проблем, конфигурация тоже нормально, а когда делаешь make, т вылазит следующая ошибка:
make all-recursive
Making all in sqlplusint
"Makefile", line 222: Need an operator
"Makefile", line 223: Need an operator
"Makefile", line 224: Need an operator
"Makefile", line 225: Need an operator
"Makefile", line 226: Need an operator
"Makefile", line 227: Need an operator
"Makefile", line 228: Need an operator
"Makefile", line 229: Need an operator
"Makefile", line 230: Need an operator
"Makefile", line 231: Need an operator
"Makefile", line 232: Need an operator
"Makefile", line 233: Need an operator
"Makefile", line 234: Need an operator
"Makefile", line 240: Need an operator
"Makefile", line 241: Need an operator
"Makefile", line 242: Need an operator
"Makefile", line 246: Need an operator
"Makefile", line 247: Need an operator
"Makefile", line 248: Need an operator
"Makefile", line 252: Need an operator
"Makefile", line 253: Need an operator
"Makefile", line 254: Need an operator
make: fatal errors encountered -- cannot continue
*** Error code 1Stop in /tmp/mysql++-1.7.9.
*** Error code 1Stop in /tmp/mysql++-1.7.9.
И что с этим делать? :(
>>Т.е. надо бы как-то его придавить процесс то этот.
>
>Вообще то, насколько я знаю, pclose ожидает завершения child процесса, поэтому
>по идее parent не должен завершится до окончания вызова pclose, т.е.
>раньше чем child.так то оно, так, только если дочерний процесс крутиться и останавливаться не собирается, пида его мы не знаем, то и родительский будет стоят ожидая завершения дочернего.
Сам не понимаю пока, но у меня сигнал навешанный на родитель видимо срабатывает и на дочернем, порожденным popen().
Непонятно только глюк это, или так и надо, чтобы сигналы процессов были общими (в смысле обработчики).И вообще что происходит когда я посылаю родительскому сигнал какой-нибудь,
дочерний его может получить, или для свой сигнал слать надо ?>Но мне кажется лучше использовать pipe+dup2+fork, тогда мы
>будем знать какой pid имеет child и в случае необходимости слать
>сигнал конкретному pid. Хотя возможно есть какой-нибудь способ получения >pid процесса запущенного popen, но мне он неизвестен.Спасибо, идея понятна.
>так то оно, так, только если дочерний процесс крутиться и останавливаться не
>собирается, пида его мы не знаем, то и родительский будет стоят
>ожидая завершения дочернего.Я ж написал - вместо pclose использовать kill(0,9). Тогда погибнут все :)))
>>так то оно, так, только если дочерний процесс крутиться и останавливаться не
>>собирается, пида его мы не знаем, то и родительский будет стоят
>>ожидая завершения дочернего.
>
>Я ж написал - вместо pclose использовать kill(0,9). Тогда погибнут все :)))да понял уже, написал же "идея понятна"
Я не про то, Вообще в принципе когда посылаешь сигнал дочернему процессу, порожденный получает его ? вроде не должен.