Isso deve fazer o que você quer:
$ ls > /dev/null & echo $!
Como você estava forçando o comando background em um subprocesso de várias maneiras, o primeiro shell não tinha nenhum processo em segundo plano e, portanto, $! não foi atualizado.
Agora, o processo de segundo plano é iniciado pelo mesmo shell que executa echo $! , então agora ele faz o que você quer.