Eu uso startx
para iniciar o X, que irá avaliar o meu .xinitrc
. No meu .xinitrc
inicio meu gerenciador de janelas usando /usr/bin/mywm
. Agora, se eu matar o meu WM (para testar outro WM), o X também será encerrado porque o .xinitrc
script alcançou o EOF. Então eu adicionei isso no final do meu .xinitrc
:
while true; do sleep 10000; done
Dessa forma, o X não terminará se eu matar o meu WM. Agora minha pergunta: como posso fazer um sono infinito em vez de repetir o sono? Existe um comando que irá congelar o script?
Cumprimentos
sleep infinity
, embora tenha sido interessante aprender sobre o Linux. No entanto,while true; do sleep 86400; done
deve ser um substituto adequado.infinity
é convertido em C de "string" para adouble
. Issodouble
é truncado para os valores máximos permitidostimespec
, o que significa uma quantidade muito grande de segundos (dependente da arquitetura), mas, em teoria, finita.tail
não bloqueiaComo sempre: para tudo, existe uma resposta curta, fácil de entender, fácil de seguir e completamente errada. Aqui se
tail -f /dev/null
enquadra nesta categoria;)Se você olhar com
strace tail -f /dev/null
atenção, notará que esta solução está longe de ser bloqueada! Provavelmente é ainda pior do que asleep
solução em questão, pois utiliza (no Linux) recursos preciosos como oinotify
sistema. Também outros processos que escrevem para/dev/null
fazertail
loop. (No meu Ubuntu64 16.10, isso adiciona vários 10 syscalls por segundo em um sistema já ocupado.)A pergunta era para um comando de bloqueio
Infelizmente, não existe tal coisa ..
Leia: Não conheço nenhuma maneira de arquivar isso diretamente no shell.
Tudo (par
sleep infinity
) pode ser interrompido por algum sinal. Portanto, se você quiser ter certeza de que ele não retorna excepcionalmente, ele deve ser executado em um loop, como você já fez para o seusleep
. Observe que (no Linux)/bin/sleep
aparentemente tem limite de 24 dias (vejastrace sleep infinity
), portanto, o melhor que você pode fazer provavelmente é:(Observe que acredito em
sleep
loops internamente para valores mais altos que 24 dias, mas isso significa: não está bloqueando, está fazendo um loop muito lento. Então, por que não mover esse loop para fora?).. mas você pode chegar bem perto com um nome
fifo
Você pode criar algo que realmente bloqueie, desde que não haja sinais enviados ao processo. Seguintes usos
bash 4
, 2 PIDs e 1fifo
:Você pode verificar se isso realmente bloqueia
strace
se você gosta:Como isso foi construído
read
bloqueia se não houver dados de entrada (consulte outras respostas). No entanto, otty
(aka.stdin
) Geralmente não é uma boa fonte, pois é fechado quando o usuário efetua logout. Também pode roubar alguma entrada dotty
. Não é legal.Para fazer o
read
bloco, precisamos esperar por algo como umfifo
que nunca retorne nada. Embash 4
há um comando que pode exatamente nos fornecer tal umfifo
:coproc
. Se também esperarmos o bloqueioread
(que é o nossocoproc
), estamos prontos. Infelizmente, isso precisa manter abertos dois PIDs e umfifo
.Variante com um nome
fifo
Se você não se incomodar em usar um nome
fifo
, faça o seguinte:Não usar um loop na leitura é um pouco desleixado, mas você pode reutilizá-lo
fifo
quantas vezes quiser eread
usar o terminat stouch "$HOME/.pause.fifo"
(se houver mais de uma única leitura aguardando, todos serão encerrados de uma só vez).Ou use o
pause()
syscall do LinuxPara o bloqueio infinito, há uma chamada do kernel do Linux, chamada
pause()
, que faz o que queremos: Espere para sempre (até que um sinal chegue). No entanto, ainda não existe um programa de espaço para usuário.C
Criar esse programa é fácil. Aqui está um trecho para criar um programa de Linux muito pequena chamada
pause
que faz uma pausa por tempo indeterminado (necessidadesdiet
,gcc
etc.):python
Se você não deseja compilar algo, mas já
python
instalou, você pode usá-lo no Linux:(Nota: Use
exec python -c ...
para substituir o shell atual, isso libera um PID. A solução também pode ser aprimorada com algum redirecionamento de E / S, liberando FDs não utilizados. Isso depende de você.)Como isso funciona (eu acho):
ctypes.CDLL(None)
carrega a biblioteca C padrão e executa apause()
função nela dentro de algum loop adicional. Menos eficiente que a versão C, mas funciona.Minha recomendação para você:
Fique no sono em loop. É fácil de entender, muito portátil e bloqueia a maior parte do tempo.
fonte
trap
(que modifica o comportamento do shell para sinais) nem do plano de fundo (que permite que o shell intercepte sinais do terminal, como Strg + C). Entãosleep infinity
é o suficiente (comporta-exec sleep infinity
se como se fosse a última afirmação. Para ver a diferença usarstrace -ffDI4 bash -c 'YOURCODEHERE'
). O sono em loop é melhor, porquesleep
pode retornar em determinadas circunstâncias. Por exemplo, você não deseja que o X11 seja desligado repentinamente em umkillall sleep
, apenas porque.xstartup
termina emsleep infinity
vez de um ciclo de suspensão.s6-pause
é um comando da terra do usuário a ser executadopause()
, opcionalmente ignorando vários sinais./bin/sleep
não é limitado aos 24 dias, como você diz. Seria bom se você pudesse atualizar isso. No Linux agora, esse código está ativo. Limitananosleep()
syscalls individuais a 24 dias, mas os chama em um loop. Portantosleep infinity
, não deve sair após 24 dias. Odouble
infinito positivo é convertido em astruct timespec
. Olhando norpl_nanosleep
GDB,infinity
é convertido{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }
no Ubuntu 16.04.strace
sozinho não posso provar o fato de que realmente há algum código de loop compiladosleep
, e não quero esperar 24 dias apenas para testar isso (ou descompilar/bin/sleep
). É sempre melhor programar defensivamente, se não houver provas matemáticas duras, que algo realmente seja, como parece ser. Também nunca confie em nada:killall -9 sleep
Talvez isso pareça feio, mas por que não apenas correr
cat
e esperar pela entrada para sempre?fonte
cat
isso?mkfifo pipe && cat pipe
TL; DR:
sleep infinity
dorme realmente o tempo máximo permitido, que é finito.Pensando em por que isso não está documentado em nenhum lugar, eu me preocupei em ler as fontes do GNU coreutils e descobri que ele executa aproximadamente o que segue:
strtod
de C stdlib no primeiro argumento para converter 'infinito' na precisão dupla. Portanto, assumindo a precisão dupla da IEEE 754, o valor do infinito positivo de 64 bits é armazenado naseconds
variávelxnanosleep(seconds)
( encontrado no gnulib ), por sua vez, invocadtotimespec(seconds)
( também no gnulib ) para converter dedouble
parastruct timespec
.struct timespec
é apenas um par de números: parte inteira (em segundos) e parte fracionária (em nanossegundos). A conversão ingenuamente positiva de infinito positivo para inteiro resultaria em comportamento indefinido (consulte §6.3.1.4 do padrão C); portanto, ele truncará paraTYPE_MAXIMUM (time_t)
.TYPE_MAXIMUM (time_t)
não está definido no padrão (nemsizeof(time_t)
está); então, por uma questão de exemplo, vamos escolher x86-64 de um kernel Linux recente.Isso está
TIME_T_MAX
no kernel do Linux, que é definido (time.h
) como:Note que
time_t
é__kernel_time_t
etime_t
élong
; o modelo de dados LP64 é usado, assimsizeof(long)
como 8 (64 bits).O que resulta em:
TIME_T_MAX = 9223372036854775807
.Ou seja:
sleep infinite
resulta em um tempo de sono real de 9223372036854775807 segundos (10 ^ 11 anos). E para sistemas linux de 32 bits (sizeof(long)
é de 4 (32 bits)): 2147483647 segundos (68 anos; consulte também o problema do ano 2038 ).Edit : aparentemente a
nanoseconds
função chamada não é diretamente o syscall, mas um wrapper dependente do SO (também definido no gnulib ).Há um passo extra, como resultado: para alguns sistemas onde
HAVE_BUG_BIG_NANOSLEEP
étrue
o sono é truncado para 24 dias e, em seguida, chamado em um loop. Este é o caso de algumas (ou todas?) Distribuições Linux. Observe que esse wrapper pode não ser usado se um teste de tempo de configuração for bem-sucedido ( origem ).Em particular, isso seria
24 * 24 * 60 * 60 = 2073600 seconds
(mais 999999999 nanossegundos); mas isso é chamado em um loop para respeitar o tempo total de suspensão especificado. Portanto, as conclusões anteriores permanecem válidas.Em conclusão, o tempo de suspensão resultante não é infinito, mas alto o suficiente para todos os fins práticos , mesmo que o lapso de tempo real resultante não seja portátil; isso depende do sistema operacional e da arquitetura.
Para responder à pergunta original, isso é obviamente bom o suficiente, mas se, por algum motivo (um sistema com muitos recursos), você realmente deseja evitar um temporizador adicional inútil, acho que a alternativa mais correta é usar o
cat
método descrito em outras respostas .fonte
sleep infinity
agora dormirá para sempre sem fazer loop: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinity
parece mais elegante, mas às vezes não funciona por algum motivo. Nesse caso, você pode tentar outros comandos de bloqueio, comocat
,read
,tail -f /dev/null
,grep a
etc.fonte
tail -f /dev/null
foi também uma solução trabalhando para mim em uma plataforma SaaStail -f /dev/null
também tem a vantagem de não consumir stdin. Eu usei por esse motivo.Que tal enviar um SIGSTOP para si mesmo?
Isso deve pausar o processo até que o SIGCONT seja recebido. Qual é o seu caso: nunca.
fonte
Deixe-me explicar por que
sleep infinity
funciona, embora não esteja documentado. A resposta de jp48 também é útil.O mais importante: ao especificar
inf
ouinfinity
(sem distinção entre maiúsculas e minúsculas), você pode dormir por mais tempo a sua implementação permitir (ou seja, o menor valor deHUGE_VAL
eTYPE_MAXIMUM(time_t)
).Agora vamos nos aprofundar nos detalhes. O código-fonte do
sleep
comando pode ser lido em coreutils / src / sleep.c . Essencialmente, a função faz isso:Compreensão
xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
De acordo com o gnulib / lib / xstrtod.c , a chamada de
xstrtod()
converte a stringargv[i]
em um valor de ponto flutuante e a armazena*s
, usando uma função de conversãocl_strtod()
.cl_strtod()
Como pode ser visto em coreutils / lib / cl-strtod.c ,
cl_strtod()
converte uma string em um valor de ponto flutuante usandostrtod()
.strtod()
De acordo com
man 3 strtod
,strtod()
converte uma string para um valor do tipodouble
. A página de manual dize um infinito é definido como
Embora o documento informe
, não está claro como um infinito é tratado. Então, vamos ver o código-fonte gnulib / lib / strtod.c . O que queremos ler é
Assim,
INF
eINFINITY
(não diferenciam maiúsculas de minúsculas) são consideradosHUGE_VAL
.HUGE_VAL
famíliaVamos usar o N1570 como o padrão C.
HUGE_VAL
,HUGE_VALF
EHUGE_VALL
macros são definidos no §7.12-3e em §7.12.1-5
Compreensão
xnanosleep (s)
Agora entendemos toda a essência de
xstrtod()
. Pelas explicações acima, é claro quexnanosleep(s)
vimos primeiro realmente significaxnanosleep(HUGE_VALL)
.xnanosleep()
De acordo com o código-fonte gnulib / lib / xnanosleep.c ,
xnanosleep(s)
basicamente faz isso:dtotimespec()
Esta função converte um argumento do tipo
double
em um objeto do tipostruct timespec
. Como é muito simples, deixe-me citar o código fonte gnulib / lib / dtotimespec.c . Todos os comentários são adicionados por mim.Como
time_t
é definido como um tipo integral (consulte §7.27.1-3), é natural assumirmos que o valor máximo do tipotime_t
é menor queHUGE_VAL
(do tipodouble
), o que significa que entramos no caso de estouro. (Na verdade, essa suposição não é necessária, pois, em todos os casos, o procedimento é essencialmente o mesmo.)make_timespec()
A última parede que temos que escalar é
make_timespec()
. Felizmente, é tão simples que citar o código fonte gnulib / lib / timespec.h é suficiente.fonte
Recentemente, tive uma necessidade de fazer isso. Eu vim com a seguinte função que permitirá que o bash durma para sempre sem chamar nenhum programa externo:
NOTA: Eu publiquei anteriormente uma versão disso que abriria e fecharia o descritor de arquivos a cada vez, mas descobri que em alguns sistemas fazendo isso centenas de vezes por segundo acabaria travando. Portanto, a nova solução mantém o descritor de arquivo entre as chamadas para a função. Bash irá limpá-lo na saída de qualquer maneira.
Isso pode ser chamado como / bin / sleep e permanecerá no tempo solicitado. Chamado sem parâmetros, ele travará para sempre.
Há um artigo com detalhes excessivos no meu blog aqui
fonte
Essa abordagem não consumirá recursos para manter o processo ativo.
while :; do sleep 1; done & kill -STOP $! && wait $!
Demolir
while :; do sleep 1; done &
Cria um processo fictício em segundo planokill -STOP $!
Pára o processo em segundo planowait $!
Aguarde o processo em segundo plano, isso estará bloqueando para sempre, pois o processo em segundo plano foi interrompido antesfonte
Em vez de matar o gerenciador de janelas, tente executar o novo com
--replace
ou-replace
se disponível.fonte
--replace
, sempre recebo um aviso comoanother window manager is already running
. Isso não faz muito sentido para mim.Não há espera para o processo de sono infantil.
fonte
stdin
se isso ainda estiver conectado aotty
. Se você executá-lo com< /dev/null
ele ocupado-loops. Pode ser de alguma utilidade em determinadas situações, por isso não voto negativo.