Você não pode. Variáveis atribuídas em um sub-shell não têm efeito no shell pai.
Faça isso:
count=$(timeout 10 ls -l /tmp/ | wc -l)
echo "count: $count"
Estou tentando definir a variável 'count' ao executar o comando dentro de um heredoc junto com o tempo limite, mas não consigo obter a variável 'count' fora do heredoc.
Como posso conseguir isso?
Meu script é mais complexo, mas achei que a resposta seria suficiente.
timeout 10 bash << EOC
count=$(ls -l /tmp/ | wc -l)
EOC
echo "count: $count"
Você não pode. Variáveis atribuídas em um sub-shell não têm efeito no shell pai.
Faça isso:
count=$(timeout 10 ls -l /tmp/ | wc -l)
echo "count: $count"
O que você está tentando fazer não pode funcionar, você terá que encontrar outro caminho. Quando você executa outro programa, ele tem seu próprio espaço de memória, ele não pode influenciar as variáveis no shell atual. Isso é verdade mesmo que o outro programa seja uma instância do mesmo shell que você está executando.
Usar um documento here em vez de bash -c
não altera esse fato. Seu exemplo é equivalente a timeout 10 bash -c "count=$(ls -l /tmp/ | wc -l)"
. (A propósito, isso executa ls -l /tmp/ | wc -l
no shell externo, não na instância de bash
que você gera: se você quisesse fazer o equivalente a timeout 10 bash -c "count=$(ls -l /tmp/ | wc -l)"
, precisaria usar <<\EOF
ou <<'EOF'
ou algo parecido.)
Se você só precisa obter o valor de uma variável, pode usar uma substituição de comando:
count=$(timeout 10 bash -c '…')
Se você precisar definir muitas variáveis ou uma matriz, precisará fazer alguma codificação e decodificação. Você pode obter o bash para fazer isso por você: declare -p foo bar
imprime uma maneira de definir foo
e bar
que foram citados corretamente para o shell de chamada.
eval "$(bash -c '…; declare foo bar')"
Note que isto declara variáveis localmente, então se você executá-lo em uma função, as variáveis não estarão disponíveis quando a função retornar. Se você precisar que as variáveis estejam disponíveis no retorno, será necessário atribuí-las novamente com declare -g
; isso só funciona para escalares:
f () {
eval "$(bash -c '…; declare foo bar')"
declare -g foo="$foo" bar="$bar"
}
Como alternativa, se você sabe que os valores das variáveis não podem conter novas linhas, remova declare -…
do início de cada linha na saída de declare -p
.
Eu não acho que você pode conseguir isso. O grande problema é que você tem um processo bash
avaliando um pipeline e, em seguida, armazenando o valor desse pipeline na variável count
da shell. timeout
em si não é um shell embutido no meu laptop Arch, então há um terceiro nível de processo. Como timeout
bifurca o comando que aguarda, há um terceiro nível de processo.
Isso é shell-que-invoca-timeout - > tempo limite - > bash-invoked-by-timeout - > valor-de- count
Parece-me que você precisa reorganizar seu script de shell para poder usar o valor de count
(ou seja o que for que você deseja realizar).
Se você realmente precisar do timeout
no comando, provavelmente deverá enviar a saída do comando para um arquivo e depois ler esse arquivo:
if timeout ls -l /tmp > /tmp/some.well.known.name
then
VAR=$(wc -l /tmp/some.well.known.name)
else
: handle timeout
fi
Tags bash variable here-document