Estou escrevendo um script de shell que deve ser um tanto seguro, ou seja, não passa dados seguros por meio de parâmetros de comandos e, de preferência, não usa arquivos temporários. Como posso passar uma variável para o stdin de um comando? Ou, se não for possível, como usar corretamente os arquivos temporários para tal?
105
$PATH
? Para quecat
possa ser substituído por/bin/cat "$@" | tee /attacker/can/read/this/file
Respostas:
Algo tão simples como:
fonte
echo "$blah"
é melhor.blah=-n
,blah=-e
... use em seuprintf
lugar. unix.stackexchange.com/questions/65803/…printf '%s\n' "$blah"
? Com essa única mudança (evitando as muitas armadilhas naecho
especificação de, cuja excelente resposta de Stephane entra em detalhes em Por que éprintf
melhor queecho
? Em Unix e Linux , ou que a seção USO DE APLICATIVO daecho
especificação aborda mais brevemente) é um perfeito resposta razoável.Passar um valor para
stdin
em bash é tão simples quanto:Sempre certifique-se de colocar aspas nas expressões variáveis!
fonte
<<<
há garantia de disponibilidade de herestrings , elas não estão na base POSIX, até onde eu sei. Eles funcionarão conforme o esperado, contanto que você apenas os executebash
. Eu apenas mencionei isso, porque eles disseram 'shell' e não especificamente 'bash'. Embora ele tenha marcado a pergunta combash
... então esta ainda é obviamente uma resposta aceitável.echo
método for usado devido à criação de um tubo. O comando herestring será processado inteiramente porbash
, embora nesta situação (conforme observado), é melhor saber que ele funcionará em seu bash, caso contrário, qualquer mensagem de erro produzida como resultado de não suportar herestrings também vazaria essa informação.echo
é um built-in. Não tem tubo aí, certo? É Unix, mas não pode ser tanto Unix .printf '%s\n' "$var"
produz os mesmos resultados queecho "$var"
mas não quebrará se, por exemplo ,,var=-en
e nem mesmo requer bash.Observe que as
echo "$var" | command
operações ' significam que a entrada padrão é limitada à (s) linha (s) ecoada (s). Se você também deseja que o terminal seja conectado, você precisa ser mais sofisticado:Isso significa que a (s) primeira (s) linha (s) será o conteúdo de,
$var
mas o resto virá dacat
leitura de sua entrada padrão. Se o comando não fizer nada muito sofisticado (tente ativar a edição de linha de comando ou executar comovim
faz), então tudo bem. Caso contrário, você precisa ser realmente sofisticado - eu achoexpect
ou um de seus derivados provavelmente será apropriado.As notações da linha de comando são praticamente idênticas - mas o segundo ponto-e-vírgula é necessário com as chaves, embora não seja entre parênteses.
fonte
( echo "$LIST"; cat - ) | sed 1q
isso funciona para mim, mas preciso pressionar ctrl d quando executo este script?cat -
continua a ler do teclado até EOF ou interromper, então você precisa dizer EOF digitando control-D.cat
nada se não quiser entrada de terminal, como na primeira linha. Ou você pode usarcat
para listar um arquivo. Ou ... Se quiser que o comando leia a entrada do terminal, você deve avisá-lo quando chegar ao fim da entrada. Ou você pode usar( echo "$var"; sed /quit/q - ) | command
; isso continua até que você digite uma linha contendo 'quit'. Você pode ser infinitamente criativo ao lidar com isso. Cuidado com a velha lenda urbana de um programa que parou de funcionar quando os usuários começaram a trabalhar com o Equador. Eles digitavam o nome da capital, Quito, e o programa era encerrado.echo "$LIST" | sed 1q | ...
? Tudo depende do que você faz. A<<EOF
notação deve exigir um EOF no início de uma linha por conta própria em algum lugar abaixo do arquivo. Eu não usaria, eu acho - mas ainda não tenho certeza do que você está tentando alcançar. Um simplesecho "$LIST" | command
ouecho $LIST | command
provavelmente será suficiente na prática (e é importante que você saiba o significado da diferença entre os dois).Gostei da resposta do Martin, mas tem alguns problemas dependendo do que está na variável. este
é melhor se sua variável contém "ou!
fonte
foo1=-; foo2='"'; foo3=\!; cat<<<"$foo1"; cat<<<"$foo2"; cat<<<"$foo3"
funciona bem para mim. O que exatamente os três"
fazem? AFAIK você está apenas prefixando e acrescentando uma string vazia.A
cat
não é realmente necessário, mas ajuda a estruturar o código melhor e permite que você use mais comandos entre parênteses como entrada para seu comando.fonte
$passwd
De acordo com a resposta de Martin, há um recurso bash chamado Here Strings (que é uma variante do recurso Here Documents mais amplamente suportado ).
http://www.gnu.org/software/bash/manual/bashref.html#Here-Strings
Observe que Here Strings parece ser apenas bash, então, para melhor portabilidade, você provavelmente ficaria melhor com o recurso Here Documents original, de acordo com a resposta de PoltoS:
Ou uma variante mais simples do anterior:
Você pode omitir
(
e)
, a menos que queira redirecioná-lo para outros comandos.fonte
Essa forma robusta e portátil já apareceu em comentários. Deve ser uma resposta independente.
ou
Notas:
echo
, as razões estão aqui: Por que éprintf
melhor do queecho
?printf "$var"
está errado. O primeiro argumento é o formato em que várias sequências semelhantes%s
ou\n
são interpretadas . Para passar a variável certa, ela não deve ser interpretada como formato.Normalmente, as variáveis não contêm novas linhas finais. O comando anterior (com
%s
) passa a variável como está. No entanto, as ferramentas que trabalham com texto podem ignorar ou reclamar de uma linha incompleta (consulte Por que os arquivos de texto devem terminar com uma nova linha? ). Portanto, você pode querer o último comando (com%s\n
) que anexa um caractere de nova linha ao conteúdo da variável. Fatos não óbvios:<<<"$var" my_cmd
) adiciona uma nova linha.my_cmd
, mesmo se a variável estiver vazia ou indefinida.fonte
Experimente isto:
fonte
ps -u
quando o echo está em execução?echo
é embutido, então não há processo para mostrar em psecho "$variable"
é melhor.Apenas faça:
Se var não contiver espaços, as aspas podem ser omitidas.
Se estiver usando o bash, você também pode fazer:
Evite usar echo sem -n porque ele canalizará a variável com uma quebra de linha adicionada no final.
fonte
%s
, printf não imprimirá nada.my_var="%s"; printf "$my_var";
- talvez tenteprintf "%s" "$my_var" | my_cmd
?