Sim, os processos herdam os descritores de arquivos de seus pais, quando você faz isso:
Em
php -r 'passthru("nano");'
php
herdará o stdin do shell (um dispositivo tty se invocado no prompt de um shell interativo) e nano
também o herdará (enquanto stdout é um canal usado por php
para recuperar o shell saída de nano
e passá-lo, nano
parece estar feliz com isso, nem todos os editores, você pode querer usar system()
aqui).
Em:
something | php -r 'passthru("nano");'
Você está chamando php
com stdin agora um pipe com stdout de something
na outra extremidade. E nano
herdará isso.
Se você quiser que o stdin de php
seja o canal, enquanto que nano
stdin seja qual for o stdin do shell, você precisará passar esse recurso para php
e ter php
(ou o shell executado por passthru
) torná-lo o stdin de nano
. Isso poderia ser feito com, por exemplo:
{ something 3<&- | php -r 'passthru("nano <&3 3<&-");'; } 3<&0
Quando disponibilizamos o recurso em fd 0 (stdin) no fd 3 dentro de um grupo de comando ( {...;}
), feche-o para something
, que não precisa dele ( 3<&-
), e diga o shell é executado pelo passthru
do php para restaurar o stdin daquele fd3.
Exemplo:
$ php -r 'passthru("ls -l /proc/self/fd");'
total 0
lrwx------ 1 stephane stephane 64 Mar 19 15:12 0 -> /dev/pts/38
l-wx------ 1 stephane stephane 64 Mar 19 15:12 1 -> pipe:[22538485]
lrwx------ 1 stephane stephane 64 Mar 19 15:12 2 -> /dev/pts/38
fd 0 é um dispositivo tty para interação terminal.
$ echo hello | php -r 'passthru("ls -l /proc/self/fd");'
total 0
lr-x------ 1 stephane stephane 64 Mar 19 15:12 0 -> pipe:[22539326]
l-wx------ 1 stephane stephane 64 Mar 19 15:12 1 -> pipe:[22530020]
lrwx------ 1 stephane stephane 64 Mar 19 15:12 2 -> /dev/pts/38
Agora, o stdin de ls
é um canal (o que a echo
está alimentando).
$ { echo hello 3<&- | php -r 'passthru("ls -l /proc/\$PPID/fd /proc/self/fd <&3 3<&-");';} 3<&0
/proc/9202/fd:
total 0
lr-x------ 1 stephane stephane 64 Mar 19 15:17 0 -> pipe:[22544619]
lrwx------ 1 stephane stephane 64 Mar 19 15:17 1 -> /dev/pts/38
lrwx------ 1 stephane stephane 64 Mar 19 15:17 2 -> /dev/pts/38
lrwx------ 1 stephane stephane 64 Mar 19 15:17 3 -> /dev/pts/38
lr-x------ 1 stephane stephane 64 Mar 19 15:17 4 -> pipe:[22544623]
/proc/self/fd:
total 0
lrwx------ 1 stephane stephane 64 Mar 19 15:17 0 -> /dev/pts/38
l-wx------ 1 stephane stephane 64 Mar 19 15:17 1 -> pipe:[22544623]
lrwx------ 1 stephane stephane 64 Mar 19 15:17 2 -> /dev/pts/38
O stdin de ls
foi feito novamente no dispositivo tty, enquanto seu pai (php) ainda tem o pipe em stdin (veja também o tty em fd 3 e outro pipe em fd 4, provavelmente o que está lendo a saída de ls
com).
Então, aqui, você precisa alterar seu script php para:
<?php
foreach(file("php://stdin") as $name) {
echo "Hello $name";
passthru("nano <&3 3<&-");
}
?>
E chame como:
{ printf '%s\n' World Everybody | php script.php; } 3<&0
Para passar os dois recursos (o canal de printf
e o stdin original) para php
.
Se você espera que o script php
sempre seja chamado de dentro de um terminal e que nano
sempre deve interagir com o terminal (mas, novamente, observe que php
faz seu stdout não o terminal), você pode alterá-lo para:
<?php
foreach(file("php://stdin") as $name) {
echo "Hello $name";
passthru("nano < /dev/tty");
}
?>
Onde codificamos o stdin de nano
para ser o terminal de controle.