2011-12-15 3 views
6

я закодировал основную оболочку в C для выполнения основных команд он будет выполнять команды ls, ls -al, ls -al | more и т.д.перенаправлять вывод в файл в C

я хочу, чтобы выполнить следующую команду в моей оболочке. нравится;

ls -al > a.txt 

это даст мне a.txt файл, который содержит вывод ls -al процесса. Я нашел одно решение, оно меняет команду в моей оболочке, как [command1] | tee [filename]. в этом случае он изменит ls -al > a.txt на ls -al | tee a.txt. но этот процесс также дает вывод в файл и терминал. как остановить печать вывода в терминале.

или есть лучшее решение, а не использование команды tee. заранее спасибо ...

+2

почему '|' символ перенаправления вывода работает в вашей оболочке, и '>' нет? –

ответ

10

Это результат моих испытаний вещей с dup2

Более тонкой точкой запоминания fflush в нужное время :) В противном случае, вы получите очень неожиданные результаты.

Также предпочитают fileno вместо жесткого кодирования 1 (стандартный) 2 (stderr).

Перенаправление stdin был оставлен в качестве упражнения для читателя

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(int argc, const char *argv[]) 
{ 
    int out = open("cout.log", O_RDWR|O_CREAT|O_APPEND, 0600); 
    if (-1 == out) { perror("opening cout.log"); return 255; } 

    int err = open("cerr.log", O_RDWR|O_CREAT|O_APPEND, 0600); 
    if (-1 == err) { perror("opening cerr.log"); return 255; } 

    int save_out = dup(fileno(stdout)); 
    int save_err = dup(fileno(stderr)); 

    if (-1 == dup2(out, fileno(stdout))) { perror("cannot redirect stdout"); return 255; } 
    if (-1 == dup2(err, fileno(stderr))) { perror("cannot redirect stderr"); return 255; } 

    puts("doing an ls or something now"); 

    fflush(stdout); close(out); 
    fflush(stderr); close(err); 

    dup2(save_out, fileno(stdout)); 
    dup2(save_err, fileno(stderr)); 

    close(save_out); 
    close(save_err); 

    puts("back to normal output"); 

    return 0; 
} 
+0

Большое спасибо, это работает – Zeemaan

+0

. Одна вещь, оболочка перезаписывает данные в файл, если файл был там, иначе он будет создан, тогда как его переписать. – Zeemaan

+0

@ Zeemaan: использование 'O_WRONLY | O_CREAT | O_TRUNC' должно работать (или 'creat (" cout.log ", 0600)' вместо открытого). См. [Open] (http://pubs.opengroup.org/onlinepubs/7908799/xsh/open.html) и [creat] (http://pubs.opengroup.org/onlinepubs/7908799/xsh/creat.html) – sehe

2

Перед тем, как позвонить execve(2) в новом процессе, чтобы выполнить команду, вы можете перенаправить стандартный ввод или вывод через dup2(2) системного вызова:

/* redirect stdout to a file */ 
dup2(1, some_open_file_descriptor); 

Конечно, вы необходимо иметь некоторую обработку ошибок.

3

Не используйте трубу, когда выход должен идти в файл.

Когда вы заставляете ребенка выполнять команду ls, обратите внимание на перенаправление и откройте файл; вы затем используете dup2() (или close() и dup()), так что файловый дескриптор теперь является стандартным выходом для дочернего элемента; вы закрываете дублированный дескриптор файла - тот, который возвращается open(); затем вы выполняете ls, как обычно; его стандартный вывод теперь отправляется в файл.

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

Смежные вопросы