Estou tendo problemas para depurar um programa segfaulting porque a saída logo antes do segfault é o que eu preciso, mas isso será perdido se eu estiver canalizando a saída para um arquivo. De acordo com esta resposta: https://unix.stackexchange.com/a/17339/22615 , isso ocorre porque o buffer de saída do programa é liberado imediatamente quando conectado a um terminal, mas apenas em determinados pontos quando conectado a um pipe. Algumas perguntas aqui:
Como um programa determina a que seu stdout está conectado?
Como o comando "script" produz o mesmo comportamento de quando o programa grava em um terminal?
Isso pode ser feito sem o comando script?
Informando se um descritor de arquivo aponta para um dispositivo terminal
Um programa pode dizer se um descritor de arquivo está associado a um dispositivo tty usando a
isatty()
função C padrão (que geralmente faz umaioctl()
chamada de sistema inócua específica do tty que retornaria com um erro quando o fd não aponta para um dispositivo tty) .O utilitário
[
/ pode fazer isso com seu operador.test
-t
Rastreando chamadas de função libc em um sistema GNU/Linux:
Rastreamento de chamadas do sistema:
Dizendo se aponta para um tubo
Para determinar se um fd está associado a um pipe/fifo, pode-se usar a
fstat()
chamada de sistema , que retorna uma estrutura cujost_mode
campo contém o tipo e as permissões do arquivo aberto naquele fd. AS_ISFIFO()
macro C padrão pode ser usada nessest_mode
campo para determinar se o fd é um pipe/fifo.Não existe um utilitário padrão que possa fazer um
fstat()
, mas existem várias implementações incompatíveis de umstat
comando que podem fazer isso.zsh
'sstat
embutido comstat -sf "$fd" +mode
o qual retorna o modo como uma representação de string cujo primeiro caractere representa o tipo (p
para pipe). O GNUstat
pode fazer o mesmo comstat -c %A - <&"$fd"
, mas também devestat -c %F - <&"$fd"
relatar o tipo sozinho. Com BSDstat
:stat -f %St <&"$fd"
oustat -f %HT <&"$fd"
.Dizendo se é procurável
Os aplicativos geralmente não se importam se stdout é um pipe. Eles podem se importar que seja pesquisável (embora geralmente não decidam se armazenar em buffer ou não).
Para testar se um fd é pesquisável (pipes, soquetes, dispositivos tty não são pesquisáveis, arquivos regulares e a maioria dos dispositivos de bloco geralmente são), pode-se tentar uma
lseek()
chamada de sistema relativa com um deslocamento de 0 (tão inócuo).dd
é um utilitário padrão que é uma interfacelseek()
, mas não pode ser usado para esse teste, pois as implementações não chamariamlseek()
se você solicitar um deslocamento de 0.Os shells
zsh
e têm operadores de busca internos:ksh93
Desativando o buffer
O
script
comando usa um par pseudoterminal para capturar a saída de um programa, então o stdout do programa (e stdin e stderr) será um dispositivo pseudoterminal.Quando o stdout é para um dispositivo terminal, geralmente ainda há algum buffer, mas é baseado em linha.
printf
/puts
e co não escreverão nada até que um caractere de nova linha seja gerado. Para outros tipos de arquivos, o buffer é por blocos (de poucos kilobytes).Existem várias opções para desabilitar o buffer que são discutidas em várias perguntas e respostas aqui (procure por unbuffer ou stdbuf , Não é possível redirecionar a saída de corte fornece algumas abordagens) usando um pseudo-terminal como pode ser feito por
socat
//script
/ (um script)/ 's ou injetando código no executável para desabilitar o buffer como feito por GNU's ou FreeBSD's .expect
unbuffer
expect
zsh
zpty
stdbuf