Pourquoi cette commande «at» ne s'imprime-t-elle pas sur la sortie standard?

15

Je suis un novice Linux relatif. J'essaie d'apprendre à utiliser atafin de pouvoir planifier des tâches pour commencer plus tard, sans utiliser sleep. J'ai regardé cette question précédente pour obtenir de l'aide.

Ma question est, dans l'exemple de script bash suivant que j'ai créé, pourquoi "Running" n'est jamais - autant que je sache - imprimé sur la sortie standard (c'est-à-dire ma console bash)?

#!/bin/bash

echo "Started"

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

echo "Finished"

La seule sortie que je vois est, par exemple:

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

La réponse à ma question se trouve-t-elle dans l'avertissement? Si oui, en quoi /bin/shdiffère- t -il de la sortie standard?

Andrew
la source
essayez ceci:sleep 3m; echo Running
Jasen

Réponses:

18

Car atn'exécute pas de commandes dans le contexte de votre session utilisateur connectée. L'idée est que vous pouvez planifier l'exécution d'une commande à une heure arbitraire, puis vous déconnecter et le système se chargera d'exécuter la commande à l'heure spécifiée.

Notez que la page de manuel at(1)indique spécifiquement (je souligne):

L'utilisateur recevra une erreur standard et une sortie standard de ses commandes, le cas échéant. Le courrier sera envoyé à l'aide de la commande / usr / sbin / sendmail.

Vous devez donc vérifier votre spouleur de messagerie locale ou, à défaut, les journaux de messagerie du système local. / var / spool / mail / $ USER est probablement un bon point de départ.

Notez également que le "Démarré" et le "Terminé" proviennent du script externe et n'ont rien à voir avec eux-mêmes at. Vous pouvez les retirer ou l' atinvocation et vous obtiendrez essentiellement le même résultat.

un CVn
la source
8

Comme @ MichaelKjörling l'a expliqué, toute sortie produite par votre attravail sera capturée et envoyée par e-mail. Si vous n'avez pas d' agent de transfert de courrier MTA en cours d'exécution sur votre boîte, l'e-mail peut être dans les limbes et vous ne saurez atmême pas qu'il tente de le faire.

Un MTA est un programme tel que sendmailou postfixqui peut "livrer" des e-mails à une destination appropriée. Dans ce cas, il va le remettre dans une file d'attente de messagerie (un fichier sous le répertoire /var/spool/mail) sur votre système local. Chaque utilisateur du système peut avoir une file d'attente dans ce répertoire.

Sur mon système Fedora si je démarre, sendmailla livraison du courrier local peut avoir lieu. Je l'ai généralement éteint cependant.

$ sudo service start sendmail

Maintenant, nous pouvons voir que ma file d'attente de messagerie pour mon compte d'utilisateur samlest vide:

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

Alors maintenant, nous exécutons le attravail:

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

Nous pouvons voir que le travail attend de s'exécuter avec atq:

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

En l'exécutant à nouveau après quelques minutes, nous pouvons voir que le attravail est terminé:

$ atq
$

Par ailleurs, avec mon MTA en cours d'exécution, je reçois maintenant ce message dans mon terminal:

Vous avez de nouveaux messages dans / var / spool / mail / saml

Vérifions donc:

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

Oui, nous avons du courrier, alors vérifions-le en utilisant mutt:

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

Nous avons ceci dans la "boîte de réception" de notre file d'attente de courrier:

     SS de la boîte de réception de mutt

Voyons cet e-mail:

     SS du msg de mutt

Et ça a marché.

slm
la source
@ MichaelKjörling - mutt rulz 8-)
slm
5

J'utilise Debian 8.1 (jessie)
Vous pouvez demander à la sortie «at» d'aller sur un terminal en utilisant 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>

Une minute plus tard, 'ZZZZZ' apparaîtra dans votre terminal ...

AAAfarmclub
la source
2

Les réponses ci-dessus sont la manière standard / "correcte" de le faire.

Une autre approche plus simple d'un point de vue plus «utilisateur final» consiste à faire en sorte que toute tâche planifiée ou en arrière-plan écrive sa sortie dans un fichier «journal». Le fichier peut se trouver n'importe où sur votre système, mais si la tâche s'exécute en tant que root (à partir de cron, etc.), alors quelque part sous /var/logest un bon endroit pour le mettre.

J'ai créé le /var/log/maintrépertoire et l' ai rendu lisible par tout le monde et j'ai un fichier lisible sous celui appelé "sauvegarde" où je journalise la sortie de mes scripts de sauvegarde.

J'ai créé mon propre répertoire afin que mes fichiers ne soient pas mélangés avec les éléments générés par le système.

Pour y mettre des trucs (en bash):

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

Le >>fait que les messages sont ajoutés au fichier au lieu de le remplacer à chaque fois.

Si mon script a beaucoup de sortie, j'utilise un script ou une fonction pour la sortie afin que tout soit fait de la même manière. Ci-dessous est ma version actuelle (overkill): (le truc VERBOSE est là lorsque j'exécute le script à partir d'un terminal et que je veux voir ce qui se passe à des fins de débogage.)

#!/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

Edit: atexemple simpliste qui écrit dans un fichier utilisateur

Je n'ai pas utilisé cela depuis toujours, donc je l'ai compris avec quelques scripts simples.

Le premier script planifie simplement l'événement en utilisant at. La commande elle-même pourrait simplement être tapée dans un terminal, mais je suis paresseux - surtout quand je dois le faire plusieurs fois tout en le testant sans tromper avec l'historique des commandes.

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

Le deuxième script est celui qui doit s'exécuter

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

J'ai créé les deux scripts dans un éditeur de texte, les ai enregistrés, puis les ai rendus exécutables à l'aide de chmod 700 script-file-name. Je les mets tous les deux dans mon $HOME/binannuaire pour plus de commodité, mais ils peuvent se trouver partout où mon utilisateur a un accès complet. J'utilise 700pour n'importe quel script uniquement pour les tests, mais sur un système mono-utilisateur, il pourrait tout aussi bien l'être 755.

J'ai déjà un répertoire appelé /home/bigbird/logpour enregistrer la sortie de mytest_at_script. Cela peut également se faire partout où votre utilisateur a un accès complet. Assurez-vous simplement qu'il existe avant l'exécution du script ou que le script le crée.

Pour l'exécuter, je me suis juste assuré que l'heure de la atcommande mytest_at_runétait un peu dans le futur, puis je l'ai exécutée à partir d'un terminal. J'ai ensuite attendu qu'il s'exécute et j'ai examiné le contenu 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$

Quelques notes:

Même si je cours atdepuis mon utilisateur, il ne connaît pas mon environnement tel que mon PATHet mon répertoire personnel, donc je ne le suppose pas. J'utilise des chemins complets comme je le ferais pour n'importe quel crontravail. Et si jamais je veux en faire un crontravail, je n'aurai rien à changer juste pour le faire fonctionner.

Je >>en mytest_at_scriptla sortie append dans le fichier journal au lieu de ce >qui aurait remplacé sur chaque course. Utilisez celui qui convient le mieux à votre application.

Joe
la source
pouvez-vous me fournir un exemple pour écrire la sortie dans un fichier journal à l'aide de la commande AT, j'essaie de la manière suivante, mais aucun résultat, maintenant + 1 min à> echo "" bonjour ">> / home / camsarch / cams_scripts / texsttest. txt à> <EOT>
Pavan Kumar Varma
@PavanKumarVarma - a ajouté un exemple simpliste (testé) utilisant atpour écrire dans un fichier. Il semble que vous ayez récupéré la séquence d'appel dans votre exemple. Je ne sais pas très bien atquand exécuter le travail, alors je viens de coder en dur une heure dans un avenir très proche.
Joe