Eu estou procurando uma maneira de obter a saída de um comando quando ele é executado dentro de um programa C ++. Eu olhei para usar a system()
função, mas isso apenas executará um comando. Aqui está um exemplo do que estou procurando:
std::string result = system("./some_command");
Eu preciso executar um comando arbitrário e obter sua saída. Eu olhei para o boost.org , mas não encontrei nada que me desse o que preciso.
/programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
para uma extensão da grande resposta abaixo que fornece métodos para obter oreturn code
estderr
, bem comostdout
que essa resposta já explicaRespostas:
Versão anterior ao C ++ 11:
Substitua
popen
epclose
com_popen
e_pclose
para Windows.fonte
result += buffer
, para que o tubo não esteja adequadamente fechado.int main(){ puts("ERROR"); }
.Obter stdout e stderr (e também escrever para stdin, não mostrado aqui) é fácil com o cabeçalho pstreams , que define as classes iostream que funcionam como
popen
:fonte
popen
requer que você use a API C stdio, eu prefiro a API iostreams.popen
requer que você limpe manualmente aFILE
alça, os pstreams fazem isso automaticamente.popen
aceita apenas aconst char*
para o argumento, que requer cuidado para evitar ataques de injeção de shell, o pstreams permite transmitir um vetor de seqüências semelhantesexecv
, o que é mais seguro.popen
fornece apenas um cano, o pstreams informa o PID da criança, permitindo que você envie sinais, por exemplo, para matá-lo se estiver bloqueado ou não sair. Todas essas são vantagens, mesmo que você queira apenas E / S unidirecional.pstreambuf::in_avail()
, portanto, não bloqueia. Isso permite a desmultiplexação no stdout e stderr do processo, pois cada um tem dados disponíveis.pstreambuf::in_avail()
só funciona 100% de forma confiável se o sistema operacional suportar o ioctl não-padrão do FIONREAD, mas isso é suportado (pelo menos) no GNU / Linux e Solaris.Eu usaria popen () (++ waqas) .
Mas às vezes você precisa ler e escrever ...
Parece que ninguém mais faz as coisas da maneira mais difícil.
(Supondo um ambiente Unix / Linux / Mac, ou talvez Windows com uma camada de compatibilidade POSIX ...)
Você também pode querer brincar com leituras select () e sem bloqueio.
fonte
execlp
chamada tem um erro: o últimoarg
ponteiro passado deve ser(char *) NULL
para finalizar corretamente a lista de argumentos variados (consulteexeclp(3)
a referência).Para Windows,
popen
também funciona, mas abre uma janela do console - que pisca rapidamente sobre o aplicativo de interface do usuário. Se você quer ser profissional, é melhor desativar essa "piscada" (especialmente se o usuário final puder cancelá-la).Então, aqui está minha própria versão para Windows:
(Este código é parcialmente recombinado de idéias escritas nos exemplos The Code Project e MSDN.)
fonte
wchar_t
eCreateProcessW
como uma restrição desnecessária.The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
talvez seja melhor copiar primeiro a linha de comando em um buffer separado, para impedir que o chamador altere sua entrada original.Duas abordagens possíveis:
Acho que não
popen()
faz parte do padrão C ++ (faz parte do POSIX da memória), mas está disponível em todos os UNIX com os quais trabalhei (e você parece estar mirando no UNIX desde que seu comando seja./some_command
).Com a chance de não haver
popen()
, você pode usar esystem("./some_command >/tmp/some_command.out");
, em seguida, usar as funções normais de E / S para processar o arquivo de saída.fonte
Não consegui descobrir por que o popen / pclose está ausente do Code :: Blocks / MinGW. Então, resolvi o problema usando CreateProcess () e CreatePipe ().
Aqui está a solução que funcionou para mim:
fonte
CREATE_NO_WINDOW
coisa?ListStdErr
nunca é usado.O seguinte pode ser uma solução portátil. Segue padrões.
fonte
tmpnam
é perigoso, melhor aproveitamentomkstemp
"Supondo o código simples POSIX para capturar o stdout:
Contribuições de código são bem-vindas para obter mais funcionalidades:
https://github.com/ericcurtin/execxx
fonte
Você pode obter a saída após executar um script usando um pipe. Usamos pipes quando queremos a saída do processo filho.
Então, aqui está o script que você deseja executar. Coloque-o em uma variável de comando com os argumentos utilizados pelo seu script (nada se não houver argumentos). E o arquivo em que você deseja capturar a saída do script, coloque-o em copy_fp.
Portanto, o popen executa seu script e coloca a saída no fpipe e você pode copiar tudo isso para o seu arquivo de saída.
Dessa maneira, você pode capturar as saídas dos processos filhos.
E outro processo é que você pode colocar diretamente o
>
operador apenas no comando. Portanto, se colocarmos tudo em um arquivo enquanto executamos o comando, você não precisará copiar nada.Nesse caso, não há necessidade de usar tubos. Você pode usar just
system
, e ele executará o comando e colocará a saída nesse arquivo.Você pode ler o Tutorial do YoLinux: controle Fork, Exec e Process para obter mais informações.
fonte
Observe que você pode obter saída redirecionando a saída para o arquivo e lendo-a
Foi mostrado na documentação de
std::system
Você pode receber o código de saída chamando
WEXITSTATUS
macro.fonte