Por que esse comando 'at' não é impresso na saída padrão?

13

Eu sou um novato relativo em Linux. Eu estou tentando aprender como usar at para que eu possa agendar tarefas para começar mais tarde, sem usar sleep . Eu tenho olhado para esta pergunta anterior para ajuda.

A minha pergunta é, no seguinte script bash de exemplo que eu criei, porque é que "Running" nunca - tanto quanto eu posso dizer - impresso na saída padrão (isto é, meu console bash)?

#!/bin/bash

echo "Started"

at now + 1 minutes <<EOF
echo "Running"
EOF

echo "Finished"

A única saída que vejo é, por exemplo:

Started
warning: commands will be executed using /bin/sh
job 3 at Fri Jul 12 17:31:00 2013
Finished

A resposta para minha pergunta foi encontrada no aviso? Em caso afirmativo, como /bin/sh difere da saída padrão?

    
por Andrew 12.07.2013 / 23:33

4 respostas

18

Porque at não executa comandos no contexto da sua sessão de usuário conectado. A idéia é que você pode programar um comando para rodar em um tempo arbitrário, depois sair e o sistema cuidará de executar o comando na hora especificada.

Note que a página de manual para at(1) diz especificamente (minha ênfase):

The user will be mailed standard error and standard output from his commands, if any. Mail will be sent using the command /usr/sbin/sendmail.

Portanto, você deve verificar seu spool de correio local ou, na sua falta, os logs de email do sistema local. / var / spool / mail / $ USER provavelmente é um bom lugar para começar.

Observe também que "Iniciado" e "Concluído" se originam do script externo e não têm nada a ver com at . Você pode retirá-los ou a invocação at e você obterá essencialmente o mesmo resultado.

    
por 12.07.2013 / 23:48
8

Como MichaelKjörling explicou que qualquer saída produzida pelo seu trabalho at será capturada e enviada para você via e-mail. Se você não tem um MTA - Mail Transfer Agent em execução na sua caixa, então o e-mail pode estar no limbo e você Você não saberá que at está tentando fazer isso.

Um MTA, é um programa como sendmail ou postfix que pode "enviar" e-mail para um destino apropriado. Nesse caso, ele será enviado para uma fila de mensagens (um arquivo no diretório /var/spool/mail ) em seu sistema local. Cada usuário no sistema pode ter uma fila nesse diretório.

No meu sistema Fedora, se eu iniciar sendmail , a entrega de correio local pode ocorrer. Eu normalmente tenho isso embora.

$ sudo service start sendmail

Agora, podemos ver que minha fila de e-mails da minha conta de usuário saml está vazia:

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail       0 Jul 12 19:33 saml

Agora, executamos o trabalho at :

$ at now + 1 minutes <<EOF
echo "Running"
EOF
job 96 at Fri Jul 12 19:38:00 2013

Podemos ver que a tarefa está esperando para ser executada com atq :

$ atq
96  Fri Jul 12 19:38:00 2013 a saml

Executando novamente após alguns minutos, podemos ver que a tarefa at está concluída:

$ atq
$

Aliás, com o meu MTA em execução agora recebo esta mensagem no meu terminal:

You have new mail in /var/spool/mail/saml

Então, vamos verificar:

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail     651 Jul 12 19:38 saml

Sim, recebemos e-mails, então vamos conferir usando mutt :

$ mutt -f /var/spool/mail/saml

Temos isso na "caixa de entrada" da nossa fila de mensagens:

Vamosverificarestee-mail:

E funcionou.

    
por 13.07.2013 / 01:41
3

Estou executando o Debian 8.1 (jessie)
Você pode ter a saída 'at' indo para um terminal usando tty.

$ tty
/dev/pts/1

$ at now + 1 min
warning: commands will be executed using /bin/sh
at> echo 'ZZZZZ' > /dev/pts/1
at> <EOT>

Um minuto depois, e 'ZZZZZ' aparecerá no seu terminal ...

    
por 02.07.2015 / 12:56
2

As respostas acima são a maneira padrão / "correta" de fazê-lo.

Outra abordagem que é mais simples de um ponto de vista mais "usuário final" é fazer com que qualquer tarefa agendada ou em segundo plano grave sua saída em um arquivo "log". O arquivo pode estar em qualquer lugar no seu sistema, mas se a tarefa estiver sendo executada como raiz (de cron , etc.), então, em algum lugar abaixo de /var/log é um bom lugar para colocá-lo.

Eu criei o diretório /var/log/maint e o deixei legível por todos e tenho um arquivo legível sob o chamado "backup", no qual faço o registro da saída dos meus scripts de backup.

Eu fiz meu próprio diretório para que meus arquivos não se misturem com as coisas geradas pelo sistema.

Para colocar coisas lá (no bash):

BACKUP="/var/log/maint/backup"
echo "my message" >> "${BACKUP}"

O >> faz com que as mensagens sejam anexadas ao arquivo em vez de sobrescrevê-lo a cada vez.

Se meu script tiver muitos resultados, utilizarei um script ou uma função para saída para que tudo seja feito da mesma forma. Abaixo está minha versão atual (overkill): (o material VERBOSE está lá para quando eu estou rodando o script de um terminal e quero ver o que está acontecendo para fins de depuração).

#!/bin/bash
## backup_logger
## backup system logging module
## Copyleft 01/20/2013 JPmicrosystems
## Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]
## If present, -v says log to console as well as to the log file
## <caller> is the name of the calling script
## If <caller> <log message text> is not present, write a blank line to the log

## Must be placed in path, like ~/bin
## If log is owned by root or another user, then this must run as root ...
## If not, it just aborts

##source "/home/bigbird/bin/bash_trace"  ## debug
SCRIPT_NAME="$(basename $0)"
USAGE="Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]"
SYSLOGDIR='/var/log/maint'
SYSLOGFILE="${SYSLOGDIR}/backup.log"

LOGGING=1
VERBOSE=0
if [ "${1}" == "-v" ]
then
  VERBOSE=1
  shift
fi

##LOGGING=0  ## debug
##VERBOSE=1  ## debug

## Only zero or two parameters allowed - <caller> <log message text>
RC=0
if [ "$#" -eq 1 ] || [ "$#" -gt 2 ]
then
  echo "${USAGE}"
  RC=1
else
  if [ ! -w "${SYSLOGFILE}" ]
  then
    touch "${SYSLOGFILE}"
    if [ $? -ne 0 ]
    then
      echo -e "$(date) ${1} ${2}"
      echo "${SCRIPT_NAME} Can't write to log file [${SYSLOGFILE}]"
      RC=1
      exit ${RC}
    fi
  fi

  if [ -n "${1}" ]
  then
    (( LOGGING )) && echo -e "$(date) ${1} ${2}"  >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo -e "$(date) ${1} ${2}"
  else
    (( LOGGING )) && echo "" >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo ""
  fi
fi

exit $RC

Editar: simplista at exemplo que grava em um arquivo de usuário

Não usei isso para sempre, então descobri com alguns scripts simples.

O primeiro script apenas agenda o evento usando at . O comando em si pode ser digitado em um terminal, mas eu sou preguiçoso - especialmente quando tenho que fazer várias vezes enquanto o testo sem me enganar com o histórico de comandos.

#!/bin/bash
## mytest_at_run
## Schedule a script to run in the immediate future
echo "/home/bigbird/bin/mytest_at_script" | at 00:56

O segundo script é o que está programado para ser executado

#!/bin/bash
## mytest_at_script
## The script to be run later
echo "$(date) - is when this ran" >> /home/bigbird/log/at.log

Eu criei ambos os scripts em um editor de texto, salvei-os e, em seguida, criei cada executável usando chmod 700 script-file-name . Coloco os dois no meu diretório $HOME/bin por conveniência, mas eles podem estar em qualquer lugar em que o usuário tenha acesso total. Eu uso 700 para qualquer script que seja apenas para testes, mas em um sistema de usuário único, poderia ser também 755 .

Já tenho um diretório chamado /home/bigbird/log para salvar a saída de mytest_at_script . Isso também pode estar em qualquer lugar em que o usuário tenha acesso total. Apenas certifique-se de que existe antes de o script ser executado ou de o script criá-lo.

Para executá-lo, certifiquei-me de que o tempo do comando at em mytest_at_run fosse um pouco futuro e, em seguida, executei-o em um terminal. Eu esperei até que ele corresse e examinasse o conteúdo de $HOME/log/at.log .

bigbird@sananda:~/bin$ cat ~/log/at.log
Fri Sep 14 00:52:18 EDT 2018 - is when this ran
Fri Sep 14 00:56:00 EDT 2018 - is when this ran
bigbird@sananda:~/bin$

Algumas notas:

Embora eu esteja executando at do meu usuário, ele não conhece meu ambiente, como meu PATH e meu diretório pessoal, portanto, não presumo disso. Eu uso caminhos completos como eu faria para qualquer trabalho cron . E se eu quiser fazer um trabalho com cron , não precisarei alterar nada apenas para executá-lo.

Eu usei >> em mytest_at_script para anexar a saída ao arquivo de log em vez de > , o que teria sido substituído em todas as execuções. Use o que melhor se adequar à sua aplicação.

    
por 19.07.2013 / 22:50

Tags