Existem vários problemas aqui. Primeiro, timeout toma como argumento um comando único . Então, quando você escreve
timeout 10s ping -c 5 www.google.com | awk '{print "from local to google |", $0;}'
o que acontece é mais ou menos isso:
( timeout 10s ping -c 5 www.google.com ) | awk '{print "from local to google |", $0;}'
Ou seja. timeout mata ping , não o tubo inteiro, e assim você recebe de volta o código de saída do tubo (ou seja, awk ).
Para obter o código de saída de timeout , você precisa de um subshell. Mas como timeout toma como argumento um único comando, você precisa escrever isso explicitamente:
timeout 10 sh -c 'ping ... | awk ...' sh
Como alternativa, você poderia apenas definir o tempo do último comando no canal (ou seja, awk ):
ping ... | timeout 10 awk ...
Isso deve funcionar bem para ping | awk , mas pode ser propenso a condições de corrida para outros comandos. E se ping produzir muita saída, você também poderá obter um SIGPIPE, para matar o ouvinte.
Voltando à sua pergunta, você também quer colocar tudo isso em segundo plano. Para obter o código de saída de um comando em segundo plano, você precisa wait :
timeout 10 sh -c 'ping ... | awk ...' sh &
wait $!
echo $?
Infelizmente, bash não possui um wait assíncrono, o que acaba com o propósito de executar os comandos em segundo plano. Você pode, no entanto, executar outros comandos antes de wait .