AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 408804
Accepted
Arcticooling
Arcticooling
Asked: 2017-12-05 12:00:38 +0800 CST2017-12-05 12:00:38 +0800 CST 2017-12-05 12:00:38 +0800 CST

daqui a algum tempo faça algo (e talvez também mostre o resultado no console)

  • 772

Eu uso o servidor Ubuntu 16.04 e desejo usar o utilitário atem minha sessão atual para fazer algo daqui a 1 minuto (digamos, um echo), sem fornecer uma data e hora específicas - apenas 1 minuto à frente da hora atual.

Isso falhou:

echo 'hi' | at 1m

atA razão pela qual escolho sleepé porque o sono prejudica a sessão atual e, portanto, é mais adequado para atrasar os comandos em outra sessão, em vez daquela com a qual trabalhamos na maior parte do tempo. AFAIR, atnão se comporta desta forma e não vai atrapalhar minha sessão.

Atualização_1

Pela resposta de Pied Piper, tentei:

(sleep 1m; echo 'hi')  &

Eu tenho um problema com este método: O stream "hi" é impresso dentro do meu prompt primário e também adiciona um prompt secundário vazio ( _) logo abaixo do prompt primário que o contém, veja:

USER@:~# (sleep 1m; echo 'hi')  &
[1] 22731
USER@:~# hi
^C
[1]+  Done

Atualização_2

Pela resposta de Peter Corde, tentei:

(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)

Isso funciona corretamente no Bash 4.4, mas não em algumas versões mais antigas, aparentemente (veja os comentários na resposta). Eu pessoalmente uso o Bash 4.3 em meus próprios ambientes.

console stdout
  • 6 6 respostas
  • 1753 Views

6 respostas

  • Voted
  1. Marcelo
    2017-12-05T12:40:04+08:002017-12-05T12:40:04+08:00

    O correto no uso é at <timespec>, onde <timespec>é a especificação de tempo. Você também pode usar a -fopção para especificar o arquivo que contém os comandos a serem executados. Se -fnenhum redirecionamento for usado, o at irá ler os comandos para executar a partir do stdin (entrada padrão).

    No seu exemplo, para executar "algum comando" (escolhi "algum comando" para ser "echo hi" no exemplo abaixo) um minuto logo após pressionar enter (agora), o pretendido <timespec>a ser usado é now + 1 minute. Portanto, para obter o resultado desejado com uma solução one-liner, use o comando abaixo:

    echo 'echo hi' | at now + 1 minute

    Isso é suposto (e fará) para executar o echo hicomando após um minuto. O problema aqui é que o echo hicomando será executado pelo comando at em um tty fictício e a saída será enviada para a caixa de correio do usuário (se estiver configurada corretamente - o que requer uma explicação mais extensa sobre como configurar uma caixa de correio em uma máquina unix e não faz parte do escopo desta questão). O resultado final é que você não poderá ver diretamente o resultado echo hino mesmo terminal em que emitiu o comando. A alternativa mais fácil é você redirecioná-lo para "algum arquivo", por exemplo:

    echo 'echo hi > /tmp/at.out' | at now + 1 minute

    No exemplo acima, "some file" é /tmp/at.oute o resultado esperado é que o arquivo at.outem /tmp seja criado após um minuto e contenha o texto 'hi'.

    Além do now + 1 minuteexemplo acima, muitas outras especificações de tempo podem ser usadas, mesmo algumas complexas. O comando at é inteligente o suficiente para interpretar os bastante legíveis por humanos, como os exemplos abaixo:

    now + 1 day, 13:25, mid‐night, noon, ...

    Consulte a página man de at para obter mais informações sobre as possíveis especificações de tempo, pois as possíveis variações são bastante extensas e podem incluir datas, horas relativas ou absolutas, etc.

    • 13
  2. PiedPiper
    2017-12-05T12:22:23+08:002017-12-05T12:22:23+08:00

    Execute o sleepem um subshell:

    (sleep 60; echo -e '\nhi')  &
    

    Nota: no Linux você pode dar o argumento para dormir em segundos ou com um sufixo s/m/h/d (para segundos, minutos, horas, dias). No BSD o argumento tem que ser em segundos

    • 7
  3. Best Answer
    Peter Cordes
    2017-12-05T17:04:23+08:002017-12-05T17:04:23+08:00

    O stream "hi" é impresso no meu prompt (no stdin) e não no meustdout

    Não, não está " impresso no seu stdin".

    Se você pressionasse Enter, ele não tentaria executar hicomo um comando. Só que o plano de fundo foi echoimpresso hienquanto o cursor estava após o seu prompt.


    Talvez você queira imprimir uma nova linha inicial , como (sleep 1m && echo -e '\nhi' &). (Ajuste conforme necessário para o echoseu shell. Ou use printfpara portabilidade.)

    Coloquei &dentro do subshell para "rejeitar" o trabalho em segundo plano, assim você também evita o "ruído" do [1]+ Done. Com &&entre os comandos, &aplica-se a toda a cadeia de comandos compostos, então ele retorna ao prompt do shell imediatamente, em vez de esperar para sleepsair como você faria com(sleep 1; echo ... &)

    Aqui está o que acontece (com 1 segundo de atraso):

    peter@volta:~$ (sleep 1 && echo -e '\nhi' &)
    peter@volta:~$ 
    hi
           # cursor is at the start of this empty line.
    

    O Bash não sabe que echoimprimiu algo, então não sabe que precisa reimprimir seu prompt ou limpar a tela. Você pode fazer isso manualmente com control-L.

    Você poderia escrever uma função de shell que faz com que o bash reimprima seu prompt após o echotérmino . Apenas fazer echo "$PS1"não reproduzirá nenhum caractere já digitado. kill -WINCH $$no meu sistema obtém o bash para reimprimir sua linha de prompt sem limpar a tela, deixando hiuma linha sozinha antes do prompt. SIGWINCH é enviado automaticamente quando o tamanho da JANELA muda, e a resposta do bash a ele acontece para fazer o que queremos.

    Pode funcionar com outros shells, mas não estou tentando torná-lo 100% portátil / POSIX. ( Infelizmente, isso só funciona no bash4.4, não no bash4.3, ou depende de alguma configuração que desconheço )

      # bash4.4
    peter@volta:~$ (sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
    peter@volta:~$ ljlksjksajflasdf dfas      # typed in 2 seconds
    hi
    peter@volta:~$ ljlksjksajflasdf dfas      # reprinted by Bash because of `kill -WINCH`
    

    Você poderia facilmente agrupar isso em uma função de shell que recebe um argumento de suspensão e uma mensagem.

    O bash 4.3 não reimprime seu prompt após o SIGWINCH, então isso não funciona lá. Ativei shopt -s checkwinsizeem ambos os sistemas, mas só funciona no sistema Bash 4.4 (Arch Linux).

    Se não funcionar, você pode tentar (sleep 2 && echo -e '\nhi' && echo "$PS1" &), que "funciona" se a linha de comando estiver vazia. (Também ignora a possibilidade PROMPT_COMMANDdefinida.)


    Não há uma maneira realmente limpa de fazer com que a saída do terminal se misture com o que você estiver fazendo em seu terminal mais tarde, quando o cronômetro disparar. Se você estiver no meio da rolagem de algo em less, poderá facilmente perdê-lo.

    Se você está procurando algo com resultados interativos, sugiro reproduzir um arquivo de áudio. por exemplo, com um player de linha de comando como mpv(bom fork do MPlayer2). Ou escolha um arquivo de vídeo para abrir uma nova janela.

    (sleep 1 && mpv /f/share/music/.../foo.ogg </dev/null &>/dev/null &)
    

    Você pode querer echoabrir um novo xterm / konsole / gnome-terminal. Use uma opção que mantenha o terminal aberto após a saída do comando.

    • 6
  4. Austin Hemmelgarn
    2017-12-05T12:34:57+08:002017-12-05T12:34:57+08:00

    Isso falhou porque você está canalizando a saída de echo "hi", que é apenas hipara at, mas atespera que sua entrada possa ser executada pelo shell padrão do sistema (geralmente bash, mas às vezes algo diferente dependendo do sistema).

    Este:

    at 1m << EOF
    echo "hi"
    EOF
    

    vai conseguir o que você parece estar tentando fazer. Ele usa uma construção de shell chamada 'documento aqui', que geralmente é a maneira aceita de fazer esse tipo de coisa (porque ele lida com várias linhas melhor do que usar o echocomando e não requer a criação de um novo arquivo como você precisaria com cat) e traduz para o equivalente um pouco mais complicado usando echo:

    echo 'echo "hi"' | at 1m
    

    Provavelmente vale a pena notar que atenviará qualquer saída de comando para o usuário que invocou o atcomando, em vez de enviar a saída para o terminal como um comando atrasado usando sleepem um subshell faria. Em particular, isso significa que, a menos que você tenha feito alguma personalização do sistema ou pretenda ler seu spool de correio local, não poderá obter a saída dos comandos executados por meio de at.

    • 3
  5. Bruce
    2017-12-09T01:22:39+08:002017-12-09T01:22:39+08:00

    Combine a resposta de @Peter Cordes e esta resposta https://stackoverflow.com/questions/23125527/how-to-return-to-bash-prompt-after-printing-output-from-backgrounded-function/23125687#23125687

    O código abaixo é da última resposta, com uma pequena alteração minha. Compile-o para arquivar a.out (qualquer nome que você quiser)

    #include <sys/ioctl.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
            char *tty = "/dev/tty";
            if (argc > 1)
                    tty = argv[1];
            int fd = open(tty, O_WRONLY);
    
            int i;
            char buf[] = "\n";
            for (i = 0; i < sizeof buf - 1; i++)
                    if (ioctl(fd, TIOCSTI, &buf[i]))
                            perror("ioctl");
            close(fd);
            return 0;
    }
    

    Em seguida, execute o comando abaixo. (Coloquei a.out no diretório /tmp/, talvez seja necessário alterar para o seu)

    (sleep 2 && echo -e '\nhi' && /tmp/a.out &)
    

    ou

    (sleep 2 && echo -e '\nhi' && /tmp/a.out /proc/$$/fd/0 &)
    

    BTW, kill -WINCH $$funciona muito bem para mim com Bash 4.3 no Gentoo.

    • 2
  6. user1404316
    2017-12-08T20:17:57+08:002017-12-08T20:17:57+08:00

    Com base nas respostas acima, você pode fazer com que o comando incorporado direcione sua saída para o seu terminal, assim:

    echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute

    O ttycomando retorna o caminho do dispositivo do seu terminal atual, colocando-o no $(...)bash para executá-lo em um sub-shell, e o comando kill envia um sinal para o processo atual que fará com que o bash reimprima seu prompt $PS1.

    • 1

relate perguntas

  • Ecoar algo em segundo plano, mas vê-lo mesmo se você reiniciou ou teve um corte de energia?

  • Como posso fazer meu console framebuffer funcionar?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve