¿Por qué este comando 'at' no se imprime en la salida estándar?

15

Soy un novato relativo de Linux. Estoy tratando de aprender a usar atpara poder programar tareas para que comiencen más tarde, sin usar sleep. He estado mirando esta pregunta anterior en busca de ayuda.

Mi pregunta es, en el siguiente script de bash de muestra que he creado, ¿por qué "Running" nunca, por lo que puedo decir, se imprime en la salida estándar (es decir, mi consola bash)?

#!/bin/bash

echo "Started"

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

echo "Finished"

El único resultado que veo es, por ejemplo:

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

¿La respuesta a mi pregunta se encuentra en la advertencia? Si es así, ¿en qué se /bin/shdiferencia de la salida estándar?

Andrés
fuente
intente esto:sleep 3m; echo Running
Jasen

Respuestas:

18

Porque atno ejecuta comandos en el contexto de su sesión de usuario conectada. La idea es que puede programar un comando para que se ejecute en un momento arbitrario, luego cierre la sesión y el sistema se encargará de ejecutar el comando a la hora especificada.

Tenga en cuenta que la página del manual at(1)dice específicamente (mi énfasis):

El usuario recibirá por correo un error estándar y una salida estándar de sus comandos, si corresponde. El correo se enviará utilizando el comando / usr / sbin / sendmail.

Por lo tanto, debe verificar su cola de correo local o, en su defecto, los registros de correo del sistema local. / var / spool / mail / $ USER es probablemente un buen lugar para comenzar.

También tenga en cuenta que "Comenzado" y "Finalizado" se originan en el guión externo y en sí mismos no tienen nada que ver aten absoluto. Podría sacarlos o la atinvocación y obtendrá esencialmente el mismo resultado.

un CVn
fuente
8

Como @ MichaelKjörling lo ha explicado, cualquier salida producida por su attrabajo será capturada y enviada a usted por correo electrónico. Si no tiene un MTA - Mail Transfer Agent en ejecución en su casilla, entonces el correo electrónico puede estar en el limbo y no sabrá que atincluso está intentando hacerlo.

Una MTA, es un programa como sendmailo postfixque puede "entregar" correos electrónicos a un destino apropiado. En este caso, lo entregará a una cola de correo (un archivo en el directorio /var/spool/mail) en su sistema local. Cada usuario en el sistema puede tener una cola en este directorio.

En mi sistema Fedora, si inicio, sendmailpuede ocurrir una entrega de correo local. Aunque normalmente lo tengo apagado.

$ sudo service start sendmail

Ahora podemos ver que mi cola de correo para mi cuenta de usuario samlestá vacía:

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

Entonces ahora corremos el attrabajo:

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

Podemos ver que el trabajo está esperando para ejecutarse con atq:

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

Al ejecutarlo nuevamente después de un par de minutos, podemos ver que el attrabajo está completo:

$ atq
$

Por cierto, con mi MTA ejecutándose ahora recibo este mensaje en mi terminal:

Tiene correo nuevo en / var / spool / mail / saml

Así que veamos:

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

Sí, tenemos correo, así que echemos un vistazo usando mutt:

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

Tenemos esto en la "bandeja de entrada" de nuestra cola de correo:

     ss de la bandeja de entrada de mutt

Echemos un vistazo a este correo electrónico:

     ss del mensaje de mutt

Y funcionó.

slm
fuente
@ MichaelKjörling - mutt rulz 8-)
slm
5

Estoy ejecutando Debian 8.1 (jessie)
Puede hacer que la salida 'at' vaya a una 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>

Un minuto después, y 'ZZZZZ' aparecerá en su terminal ...

AAAfarmclub
fuente
2

Las respuestas anteriores son la forma estándar / "correcta" de hacerlo.

Otro enfoque más simple desde un punto de vista más de "usuario final" es hacer que cualquier tarea programada o en segundo plano escriba su salida en un archivo "log". El archivo puede estar en cualquier parte de su sistema, pero si la tarea se ejecuta como root (desde cron, etc.), entonces en algún lugar debajo /var/loges un buen lugar para colocarlo.

Creé el /var/log/maintdirectorio y lo hice legible para todos y tengo un archivo legible debajo de eso llamado "copia de seguridad" donde registro la salida de mis scripts de copia de seguridad.

Creé mi propio directorio para que mis archivos no se mezclen con las cosas generadas por el sistema.

Para poner cosas allí (en bash):

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

Esto >>hace que los mensajes se agreguen al archivo en lugar de sobrescribirlo cada vez.

Si mi script tiene mucha salida, uso una secuencia de comandos o función para la salida para que todo se haga igual. A continuación se muestra mi versión actual (overkill): (el material VERBOSE está ahí para cuando estoy ejecutando el script desde una terminal y quiero ver lo que está sucediendo con fines de depuración).

#!/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: atejemplo simplista que escribe en un archivo de usuario

No he usado esto para siempre, así que lo descubrí con un par de guiones simples.

El primer script simplemente programa el evento usando at. El comando en sí solo podría escribirse en un terminal, pero soy flojo, especialmente cuando tengo que hacerlo varias veces mientras lo pruebo sin engañar con el historial 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

El segundo script es el que está programado para ejecutarse.

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

Creé ambos scripts en un editor de texto, los guardé y luego los hice ejecutables usando chmod 700 script-file-name. Los puse a ambos en mi $HOME/bindirectorio por conveniencia, pero podrían estar en cualquier lugar donde mi usuario tenga acceso completo. Lo uso 700para cualquier script que sea solo para pruebas, pero en un solo sistema de usuario, podría serlo 755.

Ya tengo un directorio llamado /home/bigbird/logpara guardar la salida de mytest_at_script. Esto también puede estar en cualquier lugar donde su usuario tenga acceso completo. Solo asegúrese de que exista antes de que se ejecute el script o haga que el script lo cree.

Para ejecutarlo, solo me aseguré de que el tiempo para el atcomando mytest_at_runfuera un poco en el futuro y luego lo ejecuté desde una terminal. Luego esperé hasta que corrió y examiné el contenido 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$

Algunas notas

Aunque estoy ejecutando atdesde mi usuario, no conoce mi entorno, como mi PATHy mi directorio personal, por lo que no asumo eso. Utilizo caminos completos como lo haría para cualquier crontrabajo. Y si alguna vez quiero que sea un crontrabajo, no tendré que cambiar nada solo para que funcione.

He utilizado >>en mytest_at_scripta adjuntar la salida al archivo de registro en lugar de >lo que habría reemplazado en cada carrera. Use el que mejor se adapte a su aplicación.

Joe
fuente
¿Me puede dar algún ejemplo para escribir la salida en el archivo de registro utilizando el comando AT, estoy intentando de la siguiente manera pero no hay resultado, ahora + 1 min en> echo "" hello ">> / home / camsarch / cams_scripts / texsttest. txt en> <EOT>
Pavan Kumar Varma
@PavanKumarVarma: se agregó un ejemplo simplista (probado) atpara escribir en un archivo. Parece que tienes la secuencia de llamada al revés en tu ejemplo. No soy muy bueno para decir atcuándo ejecutar el trabajo, así que solo codifiqué un momento en un futuro muy cercano.
Joe