{ echo 'exec <&3 3<&-; id' | sh -si; } 3<&0
Parece funcionar com a maioria das implementações sh
. Pedimos por um shell interativo com -i
(caso contrário, alguns shells o desativariam com base no fato de que stdin não é um dispositivo terminal), inicie com o stdin do shell sendo o pipe, mas com exec <&3
instruí-lo a alterá-lo para o stdin original (externo) que salvamos anteriormente no descritor de arquivo 3 com 3<&0
.
Fazemos isso antes executando id
, mas ainda no mesmo comando line , para que stdin seja restaurado para id
também. Não importa para id
, pois ele não lê seu stdin, mas seria comandos interativos como editores ou shells.
Por que você vê o que você digita em (echo id | cat) | sh
. Parece que sua implementação de sh
, que parece ser uma versão muito antiga do bash
, está sendo executada no modo interativo. Você pode ver isso com o fato de que está emitindo um prompt como se -i
fosse usado.
Em seguida, ele implementa seu próprio editor de linhas, mas não desativa o editor de linha próprio do dispositivo tty (porque seu stdin é o pipe e não o dispositivo tty), então você obtém o eco do que digita na linha de dispositivo tty disciplina, e uma vez que você pressiona enter, cat
vê todo o conteúdo desse buffer de linha incluindo uma nova linha de uma vez do pipe que ele escreve diretamente para bash
, e bash
gera o echo
do que parte de seu próprio editor de linhas.
Eu suspeito que, se você fez:
stty -icanon -echo; (echo id; cat) | sh; stty sane
Você obteria um comportamento melhor e poderia usar as funcionalidades de edição de linha readline, já que bash
receberia todos os caracteres que digitar diretamente conforme eles surgirem.
Para outras opções para que um comando seja executado automaticamente antes que o usuário assuma um shell interativo, consulte: