Linux crontab output redirection does not take effect

  • 2020-12-09 01:14:52
  • OfStack

The problem

In LINUX, tasks performed periodically are typically handled by the cron daemon [ps-ef |grep cron]. cron reads one or more configuration files that contain the command line and its call time.

The configuration file for cron is called "crontab", short for "cron table".

Recently, a timed task was added to crontab that will have normal output by default after execution. In order to ensure that the exception information during task execution can also be caught, so as to facilitate problem location, I wrote this command in crontab:


01 09 * * * cd /opdir/test/ && ./test.sh &>>test.log

The above command is easy to understand. Every day at 9:01, the test.sh script is executed and the script's stdout and stdout are all redirected to the file test.log. It turned out that the script was executing correctly, but there was nothing in the log file test.log.

To solve and explain this problem, let's first briefly introduce the problem of redirection in linux system

concept

In Linux system:

1: Represents standard output (stdout), which is output to the screen by default

2: Represents standard error output (stderr), which is output to the screen by default

In normal times, we often use the following method to redirect the result of script execution:


bash test.sh >test.out // The standard output of the script is written to the file test.out , Standard error output is printed directly on the screen   Is equivalent to: bash test.sh 1>test.out
bash test.sh >test.out 2>&1 // Both standard output and standard error output are written to test.out And it doesn't cover each other, which is equivalent to  bash test.sh &>test.out
bash test.sh >test.out 2>test.out // Both standard output and standard error output are written to test.out , the problem of mutual coverage will occur, which is not recommended under normal circumstances 
bash test.sh &>test.out // Equivalent to the first 2 methods 

Compare the above effects:

Type 1: Error output on screen, normal output in file test.out


root@mengalong:~/opdir/mengalong/t/t# cat test.sh
#!/bin/bash
t
date

root@mengalong:~/opdir/mengalong/t/t# bash test.sh >test.out
test.sh: line 2: t: command not found
root@mengalong:~/opdir/mengalong/t/t# cat test.out
Wed Oct 31 11:07:24 CST 2018

Type 2: Both error output and normal output are redirected to file test.out


root@mengalong:~/opdir/mengalong/t/t# bash test.sh >test.out 2>&1
root@mengalong:~/opdir/mengalong/t/t# cat test.out
test.sh: line 2: t: command not found
Wed Oct 31 11:09:02 CST 2018

Type 3: Error output and normal output overwrite each other


root@mengalong:~/opdir/mengalong/t/t# bash test.sh >test.out 2>test.out
root@mengalong:~/opdir/mengalong/t/t# cat test.out
Wed Oct 31 11:10:36 CST 2018
ot found

Fourth, for special cases, compare 1 bash test.sh 2 > & 1 > test. out and bash test sh > test.out 2 > & 1 difference:


root@mengalong:~/opdir/mengalong/t/t# bash test.sh 2>&1 >test.out
test.sh: line 2: t: command not found
root@mengalong:~/opdir/mengalong/t/t# cat test.out
Wed Oct 31 11:12:13 CST 2018

I'm just putting a 2 here > & 1 in the > test. out in front, but the result is not as we expected, error and normal output into the test. out file. This is because bash test.sh 2 > & 1 > test.out, 2 > & At 1, the error output is simply redirected to stdout, and the default value of stdout is the screen, so it is equivalent to the standard error output being redirected to the screen, not to a file. So redirection requires attention to order.

Problem solving

Back to the crontab task I wrote:


01 09 * * * cd /opdir/test/ && ./test.sh &>>test.log

According to the above conceptual analysis, this writing should be equivalent to./ test.sh > test.log 2 > & 1. The output of script execution and standard error output are all redirected to ES124en.log. But the reality is that there is nothing in the ES126en.log file.

This is because the default shell environment used by crontab is /bin/sh, which is not supported by /bin/sh & > > test.log is a redirection method, so we see that there is nothing in ES141en.log.

Therefore, the solution to the problem is to modify the redirect method of crontab:


01 09 * * * cd /opdir/test/ && ./test.sh >>test.log 2>&1

� windbag 1 sentence

During the execution of crontab, if the script output is not redirected, it will send an email to the system user by default. The email content 1 is generally stored in /var/mail/$user. If it is not cleaned up, it will fill the root partition of the server, and finally the machine cannot log in. Therefore, the recommended crontab command is as follows:


01 09 * * * cd /opdir/test/ && ./test.sh >>test.log 2>&1 </dev/null &

I'm going to add more < /dev/null & I'm not going to go into the meaning of this, but if you're interested, you can analyze it for yourself

conclusion


Related articles: