为什么此“ at”命令不能打印到标准输出?


15

我是相对的Linux新手。我正在尝试学习使用方法,at以便可以安排任务在以后的时间开始使用,而无需使用sleep。我一直在寻找这个先前的问题以寻求帮助。

我的问题是,在我创建的以下示例bash脚本中,为什么就我所知,“运行”从未打印到标准输出(即我的bash控制台)上?

#!/bin/bash

echo "Started"

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

echo "Finished"

我看到的唯一输出是例如:

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

在警告中是否找到我的问题的答案?如果是这样,/bin/sh与标准输出有何不同?


试试这个:sleep 3m; echo Running
Jasen

Answers:


18

因为at不会在您登录的用户会话的上下文中执行命令。这个想法是,您可以安排命令在任意时间运行,然后注销,系统将在指定时间执行命令。

请注意,手册页上at(1)专门说了(我的重点):

将向用户邮寄标准错误和命令中的标准输出(如果有)。邮件将使用命令/ usr / sbin / sendmail发送。

因此,您应该检查本地邮件后台处理程序,否则,请检查本地系统邮件日志。/ var / spool / mail / $ USER可能是一个不错的起点。

另请注意,“开始”和“完成”源自外部脚本,而in本身与它们完全无关at。您可以删除它们或at调用它们,并且基本上会得到相同的结果。


8

正如@MichaelKjörling解释的那样,您的at工作所产生的任何输出都将被捕获并通过电子邮件发送给您。如果您的盒子上没有正在运行的MTA-邮件传输代理,则电子邮件可能处于混乱状态,您at甚至不知道这是尝试执行的操作。

MTA是一种程序,例如sendmailpostfix可以将电子邮件“传递”到适当的目的地的程序。在这种情况下,它将把它传递到/var/spool/mail本地系统上的邮件队列(目录下的文件)中。系统上的每个用户都可以在此目录中有一个队列。

在我的Fedora系统上,如果我启动 sendmail则可能会发生本地邮件传递。我通常会关闭它。

$ sudo service start sendmail

现在我们可以看到我的用户帐户的邮件队列 saml空:

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

所以现在我们运行 at工作:

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

我们可以看到该作业正在等待运行 atq

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

几分钟后再次运行它,我们可以看到 at工作已完成:

$ atq
$

顺便说一句,在运行MTA的情况下,我现在在终端中收到以下消息:

您在/ var / spool / mail / saml中有新邮件

因此,让我们检查一下:

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

是的,我们有邮件,所以我们使用mutt以下命令进行检查:

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

我们在邮件队列的“收件箱”中有此邮件:

     mutt收件箱的ss

我们来看看这封电子邮件:

     mutt的味精

而且有效。


@MichaelKjörling-mutt rulz 8
slm

5

我正在运行Debian 8.1(jessie),
您可以使用tty将“ at”输出发送到终端。

$ tty
/dev/pts/1

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

一分钟后,“ ZZZZZ”将显示在您的终端中...


2

上面的答案是执行此操作的标准/“正确”方法。

从“最终用户”的角度来看,另一种更简单的方法是让任何计划任务或后台任务将其输出写入“日志”文件。该文件可以位于系统上的任何位置,但是如果任务以root身份运行(来自cron等),则位于/var/log可以将其放置的某个位置。

我创建了/var/log/maint目录并使其对所有人可读,并且在“ backup”下有一个可读文件,在其中记录备份脚本的输出。

我创建了自己的目录,因此文件不会与系统生成的内容混在一起。

放东西(用bash):

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

>>使得消息被追加到该文件,而不是每次都覆盖它。

如果我的脚本有很多输出,那么我会使用脚本或函数进行输出,因此一切都一样。以下是我当前的版本(过度杀伤性版本):(当我从终端运行脚本并希望了解调试时的情况时,就有VERBOSE的东西。)

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

编辑:at写入用户文件的简单示例

从来没有永远使用过,所以我用几个简单的脚本弄清楚了。

第一个脚本只是使用调度事件at。该命令本身可以直接输入到终端中,但是我很懒-尤其是当我不得不多次测试它而又不假思索命令历史的时候。

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

第二个脚本是计划运行的脚本

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

我在文本编辑器中创建了这两个脚本,然后将它们保存起来,然后使用来使它们成为每个可执行文件chmod 700 script-file-name$HOME/bin为了方便起见,我将它们都放在目录中,但是它们可以位于用户具有完全访问权限的任何位置。我使用700了仅用于测试的任何脚本,但在单个用户系统上,它也可能是755

我已经有一个名为的目录,/home/bigbird/log用于保存的输出 mytest_at_script。也可以在您的用户具有完全访问权限的任何位置。只需在脚本运行之前确保它存在或让脚本创建它即可。

要运行它,我只是做了肯定的时间at命令mytest_at_run是在未来一点点,然后从终端运行它。然后,我等待直到它运行并检查的内容$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$

一些注意事项:

即使我是at从用户那里运行的,它也不知道我的环境(例如PATH我的目录和我的主目录),因此我不认为那样。我会像使用任何cron工作一样使用完整路径。如果我想做一个cron一份工作,我将不必为了使它运行而进行任何更改。

我曾经>>mytest_at_script输出附加到日志文件而不是>这将取代它在每次运行。使用最适合您的应用程序的一种。


您能提供给我任何使用AT命令将输出写入日志文件的示例的方法吗,我正在尝试按照以下方式进行但没有结果,现在+ 1分钟于> echo“” hello“ >> / home / camsarch / cams_scripts / texsttest。的txt在> <EOT>
帕库马尔瓦玛

@PavanKumarVarma-添加了一个简单的(经过测试的)示例,at用于写入文件。看起来您的示例中的调用顺序向后。我不太擅长告诉at何时该工作,所以我只是在不久的将来对时间进行了硬编码。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.