Why would you cat /dev/null onto anything?
You'll do that to truncate a file contents while keeping the inode intact. All programs that have that file open for reading or writing wouldn't be affected outside the fact the file size would be reset to zero.
A bogus alternative often found is removing the file then creating it again:
rm file
touch file
or the similar:
mv file file.old
gzip file.old
touch file
The issue is these methods do not not prevent the old file from being kept written by whatever processes having the deleted file open at deletion time. The reason why is under Unix file systems, when you delete a file, you only unlink its name (path) from its content (inode). The inode is kept alive as long as there are processes having it open for reading or writing.
This leads to several negative effects: the logs written after the file deletion are lost as there is no straightforward/portable way to open a deleted file. As long as a process is writing to the deleted file, its content is still using space on the file system. That means that if you remove/create the file because it was filling your disk, the disk stays filled. One way to fix this latter issue is to restart the logger processes but you might not want to do that for critical services and intermediary logs would be definitively lost. There are also side effects due to the fact the file you create might not have the same permissions, owner and group than the original one. This for example could prevent a log analyzer to read the newly created file, or worse, prevent the logging process to write its own logs.
The first method, cat /dev/null > file
achieve the goal properly however, despite a tenacious urban legend, its cat /dev/null
part does absolutely nothing useful. It opens a pseudo file which is empty by design, it fails to read anything from it and finally just exits. Using this command is then a waste of keystrokes, bytes, system calls, and CPU cycles and it can be replaced without any functional change by the undoubtedly faster no-op command :
or even, with most shells, by no command at all.
Let me try a metaphor to explain how useless cat /dev/null
is. Let's say your goal is to empty a glass.
You first remove any liquid from it. That is sufficient and is precisely what (> file
) does given the fact redirections are always processed first.
Then, you pick an empty bottle (/dev/null
) and pour it in the empty glass (cat
). This is the pointless step ...
If you read your linked document to the end, you might notice the comments in this line from the enhanced version of the script:
cat /dev/null > wtmp # ': > wtmp' and '> wtmp' have the same effect.
They have indeed; too bad cat /dev/null
was kept in the code.
That means that the following code will work with all common shells (both csh
and sh
families):
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
and this will work with all shells using the Bourne syntax, like ash
, bash
, ksh
, zsh
and the likes:
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
Note however that with ancient, pre-POSIX Bourne shells, any of these commands, including cat /dev/null
won't truncate a file if it is written afterwards by a still running shell script appending to it. Instead of a zero byte file, that would be a sparse file with its size unchanged. The same would happen if the file is written by a process seeking to the position it thinks is the current one before writing.
Beware also that some alternative solutions often suggested to truncate a file do have flaws.
Both of the following ones just do not do the job. The resulting file is not empty but contains an empty line. This would break log files like wtmp
that store fixed width records.
echo > file
echo "" > file
The next one based on a BSD sh
option is not portable, POSIX doesn't specify any allowed options for echo so you might end up with a file containing a line with "-n
":
echo -n > file
That one not portable either by using a System V sh
escape sequence. Some shells will create a file containing a line with "\c
":
echo "\c" > file
That one uses a command designed to do the job. The issue is using truncate
is not portable because this command, not being specified by POSIX, might be missing from a Unix/Linux system.
truncate -s 0
Finally, here are a couple of alternatives that are portable and will properly do the job:
-1 for keeping alive the urban legend
cat /dev/null >
has some magic power.cat /dev/null
does nothing useful so can be replaced by the no-op command:
or just no command at all as the redirection alone works under most shells. – jlliagre – 2014-12-06T20:54:20.95010@jlliagre The only thing being "kept alive" is the context of the question which is focused on why the original author would do that. If you are impassioned as to dispelling the "myth" please post an answer that provides context for the original author's coding method as well as perspective on why you believe it can be replaced by other methods. – JakeGould – 2014-12-06T20:59:00.637
Cyrus already posted a correct, albeit terse, answer. – jlliagre – 2014-12-06T21:05:41.850
7@jlliagre Cyrus's answer does not address the core question of why the original author would have used that method nor the reasoning behind it. The tutorial mentioned is quite old and reasonably accepted. It is not incorrect nor does it perpetuate a supposed "urban legend." Rather it is the way one person codes versus the way another person codes. As simple as that. It is a style issue that has no negative impact on reliability or performance. – JakeGould – 2014-12-06T21:12:00.357
1Granted, posting my own reply as you suggested then. – jlliagre – 2014-12-06T21:24:31.763
1ok, but implicit in "Nothing unusual" is that typing this command is not unusual either. (Which makes sense why anyone would do this after reading your answer. Thanks.) – isomorphismes – 2014-12-09T04:59:41.100
@isomorphismes Fair enough, but you can’t always control semantics of context for documentation written essentially years ago. – JakeGould – 2014-12-09T05:03:18.840
3
truncate -s 0
would do the same thing and be less idiomatic. However, shell programmers are a conservative bunch and one might encounter systems old enough or wacky enough to be lacking that command. – Schwern – 2014-12-09T05:32:26.5801@Schwern Shell programmers defer to being conservative because you are really often using scripts/tools when jumping from system to system and you don’t have the time to finesse code from install to install. Shell programming is just weird but necessary and useful. – JakeGould – 2014-12-09T05:34:07.833
1Curious, how is this different from
echo "" > /foo/bar
which seems to me to do the same thing – skift – 2014-12-09T22:32:24.600
5@skift
cat /dev/null > /foo/bar
truncates the file;echo "" > /foo/bar
truncates it and then writes a single newline character. – David – 2014-12-10T02:59:58.5172Another advantage of this method over rm & touch is that ownership and permissions are maintained. – jjmontes – 2014-12-10T13:30:17.753
1@jjmontes That point is implied by the inode number being the same, but hey it’s not clear if you don’t know what an inode is so I have edited this to reflect that aspect more clearly. Thank you! – JakeGould – 2014-12-10T16:32:03.700
@JakeGould Oh definitely. Hence why I'm thankful to SU answerers. – isomorphismes – 2014-12-10T23:13:45.830
@skift See the responses to the answer below that uses
echo -n >file
– isomorphismes – 2014-12-10T23:15:53.130