LINUX.ORG.RU

перенаправление вывода в потомке


0

1

добрый день,

с линуксом знаком на уровне школьного курса. На работе возникла такая задача: нужно в демоне анализировать вывод некой утилиты (для конкретики пусть это будет ls -l | grep vasia). Вопрос как это сделать.

моих знаний хватило только на запуск команды и перенаправление вывода в файл, т.е. что-то наподобие

 system("ls -l | grep vasia > file")
с последующим открытием этого файла из демона и чтением из него. Коллеги на работе посмеялись над предложенным вариантом и намекнули, что можно создать новый процесс, вывод которого перенаправить в моего демона. Если честно, очень смутно помню про перенаправление потоков. Расскажите, пожалуйста, как такие задачи решают гуру линукса.

Тут все зависит от демона. Какие у него есть механизмы взаимодействия с внешним миром (file, fifo, unix socket, tcp/ip socket, ...)? Что есть, туда и лить выхлоп grep'a.

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

А у коллег сразу не мог спросить как это делать? Вообще, сто экземпляров этого примера гуглится на раз и если ты даже этого не можешь сделать, ты должен находиться не за клавиатурой компьютера, а за клавиатурой кассы в макдоналдсе. Но так и быть, я сегодня добрый. В двух словах, так:

int pipe_fd[2];
pipe(pipe_fd);    // канал для передачи данных из ребёнка

pid_t pid = fork();
if (pid == 0) {
  close(pipe_fd[0]); // этот конец используется только родителем
  // ребёнок
  dup2(pipe_fd, 1); // stdout перенаправляем в канал
  // также скорее всего понадобится настроить сигналы,
  // перенаправить stderr в /dev/null, в stdout или в
  // другой pipe, перенаправить stdin из /dev/null или
  // из другого pipe или закрыть его, закрыть файловые
  // дескрипторы > 2
  exit(system("ls -l | grep vasia")); // вызываем что нужно
  // если нужно вызвать не конвеер а всего один процесс,
  // вместо предыдущей строчки можно использовать exec()
}

close(pipe_fd[1]); // этот конец используется только ребёнком

// родитель
char buffer[512];
size_t rdbytes;
while ((rdbytes = read(pipe_fd[0], buffer, sizeof(buffer))) > 0) {
  // читаем то что пишет ребёнок
}
if (rdbytes == -1) {
  // получили ошибку
}
// получили eof
int status;
waitpid(pid, status, WEXITED); // подтираем зомби, получаем exit status ребёнка

close(pipe_fd[0]); // закрываем pipe

разумеется всё это с проверкой всех кодов возврата, pid на -1 и т.д и того что указано в комментариях.

slovazap ★★★★★ ()

вам надо создать процесс с помощью fork, далее в родителе сделать следующее: mkfifo, open(fifo), dup2(fifo, 1).

далее можно писать в stdout и все пойдет в fifo

в процессе потомке сделать на всякий случай sleep(1), open(fifo), dup2(fifo, 0) далее можно читать из fifo все, что туда записал другой процесс.

IvanR ★★★ ()

А демона можно запустить с опцией чтоб он не форкалкался и выводил все в stdout?

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