36

I'm running an application that writes to log.txt. The app was updated to a new version, making the supported plugins no longer compatible. It forces an enormous amount of errors into log.txt and does not seem to support writing to a different log file.

How can I write them to a different log?

I've considered replacing log.txt with a hard link (application can't tell the difference right?) Or a hard link that points to /dev/null. What are my options?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
MALON
  • 443
  • 1
  • 4
  • 6

7 Answers7

68

You can make a symbolic link to /dev/null and you don't need to be root:

ln -s /dev/null log.txt
V. Michel
  • 561
  • 1
  • 3
  • 5
  • 1
    This also has the advantage of being self-documenting, in that `ls -l log.txt` would show that it's a symlink to /dev/null, rather than relying on knowing that e.g. "1, 3" is somehow significant. – Monty Harder Dec 21 '16 at 19:18
32
# cp -a /dev/null log.txt

This copies your null device with the right major and minor dev numbers to log.txt so you have another null.

Devices are not known by name at all in the kernel but rather by their major and minor numbers. Since I don't know what OS you have I found it convenient to just copy the numbers from where we already know they are. If you make it with the wrong major and minor numbers, you would most likely have made some other device, perhaps a disk or something else you don't want writing to.

Joshua
  • 1,733
  • 12
  • 19
  • 1
    P.S.: I know see that the major, minor comments probably relate to a _comment_ on the question recommending use of `mknod`. Do note that comments generally receive little attention, so someone reading the question only and then your answer may be confused (as was I; also note that most people are never exposed to concepts such as major and minor device numbers). – mklement0 Dec 21 '16 at 04:58
  • 4
    It is worth noting that this command requires `sudo` (or running as the root user). Please explain (in your answer) what you mean by "the right major and minor dev numbers". – mklement0 Dec 21 '16 at 03:40
  • 3
    (I'm not the OP.) I appreciate the update, but I'm still confused about how "major and minor numbers" relate to file path `/dev/null`, as used in your command. And, I think it would help future readers to note _in your answer_ that `sudo` is required. – mklement0 Dec 21 '16 at 04:07
  • 1
    This will fail if `log.txt` is on a filesystem mounted with the `nodev` option — which, for security, it probably should be. – hobbs Dec 21 '16 at 16:14
  • For what it's worth, I did tag my OS in the post. Ubuntu 14.04 x64 – MALON Dec 21 '16 at 04:22
  • This worked really well for me, thank you! – MALON Dec 21 '16 at 03:44
  • I wouldn't recommend this. Unless you have intimate knowledge of your device major/minor numbers, looking at this later can be very confusing. Also, as stated above, you have to be root to do it, and probably for good reason. For example, if you tried to create your log.txt version of /dev/null but you used 1 1 instead of 1 3, you'd cause some extremely serious problems with your system. Far, far better is to just use a symbolic link. ln -s /dev/null log.txt You don't need to be root, and you don't have to memorize major/minor dev numbers to know what's happening. – mlv Dec 21 '16 at 14:06
  • @mklement0: bash: sudo: command not found – Joshua Dec 21 '16 at 04:08
  • @mklement0: A directory entry has a file name and an "inode number" for regular files, or, for block special or character special files ("devices"), there is a device number and device subunit number, aka major and minor numbers. See [here](https://linux.die.net/man/3/major) for more detail and links to everything you might want to know. – wallyk Dec 21 '16 at 04:14
  • 1
    @wallyk: Thanks, that's indeed good to know. But my point is: How does come into play with respect to `cp -a /dev/null log.txt` and my comments? – mklement0 Dec 21 '16 at 04:17
  • 1
    @MALON: Indeed you did, and on Ubuntu 14.04 you _do_ need `sudo` to perform this command, unless you happen to be running as user `root` (which is generally discouraged). Using `sudo` (or running as `root`) to create a hard link (this answer) or a symlink (@V.Michel's answer) may be the right solution after all, if the file must be placed in a location that _any_ user account can write to, but the point is: do note that requirement explicitly. – mklement0 Dec 21 '16 at 04:34
  • @hobbs: Turns out nodev + nosuid didn't work so well as intended. The man page even outright calls it out as doesn't work if setuidperl is installed on the system. Maybe someday they'll fix that and nodev + nosuid provide real security for mounting removable filesystems without pinning the type again. – Joshua Oct 19 '17 at 02:28
  • This makes the log file be owned by root :( – Freedo Mar 23 '21 at 06:22
  • @Freedo: `chown` is your friend. If you want your private copy of `null` to be owned by somebody else, nothing's stopping you. – Joshua Mar 23 '21 at 15:14
14

The other answers here will probably work. In particular, the symlink solution is probably going to be the easiest solution. I offer this mainly for completeness.

The solutions involing mknod (or cp -a) become problematic if the filesystem containing the file doesn't support devices (e.g., it was mounted with the nodev option, for example). And of course, hard links across filesystems simply won't work.

An alternative to hard links or creating new devices nodes is to use bind mounts, which let you mount a file or directory from one part of your filesystem tree onto another. So, for example, you can run:

mount -o bind /dev/null /path/to/log.txt

This acts a lot like a hard link, but:

  • It can operate across filesystems (because it's not based on filesystem inodes like a hard link)
  • It works on read-only filesystems (because you're not actually modifying the filesystem)

For a complete example:

bash-4.3# ls -l /var/log/boot.log
-rw-r--r--. 1 root root 7436 Dec 19 10:00 /var/log/boot.log
bash-4.3# mount -o bind /dev/null /var/log/boot.log
bash-4.3# ls -l /var/log/boot.log
crw-rw-rw-. 1 root root 1, 3 Dec 19 09:58 /var/log/boot.log
bash-4.3# echo words words words > /var/log/boot.log
bash-4.3# ls -l /var/log/boot.log
crw-rw-rw-. 1 root root 1, 3 Dec 19 09:58 /var/log/boot.log
larsks
  • 32,449
  • 5
  • 54
  • 70
6

It depends critically on HOW the application handles log.txt.

If the application just opens the existing file and writes to it then as described in other answers you can symlink it to /dev/null, symlink it somewhere else, hardlink it somewhere else (though hardlinks can't be cross filesystem so there isn't a lot of point in this) create a copy of the /dev/null device node there etc.

OTOH if the application deletes and recreates log.txt none of that will work. You could symlink the whole directory somewhere else to redirect the writes to a different filesystem but thats about it and you would have to deal with other stuff in the directory.

I guess if you really wanted you could create a custom overlay filesystem that passed most operations right through while throwing away any attempts to create a file called log.txt.

plugwash
  • 4,242
  • 1
  • 18
  • 32
3

Well, one ungraceful method with named pipe:

# create a named pipe
mkfifo /path/to/log.txt
# read contents from the pipe and redirect them to /dev/null
cat /path/to/log.txt > /dev/null

you almost can do anything with the dumped log, such as filter or send over nc.

user3824053
  • 243
  • 4
  • 11
0

chattr +i log.txt the first time and the application won’t delete the file anymore.

Marco Marsala
  • 353
  • 1
  • 4
  • 14
-2

Consider making the file an actual null device. A file "log.txt" created with mknod, with the right file type and same minor and major numbers, will act as a null device because it is.

rackandboneman
  • 471
  • 2
  • 5