15

I will run the following script:

#!/bin/bash
./myprogram

#get exit code
exitvalue=$?

#log exit code value to /var/log/messages
logger -s "exit code of my program is " $exitvalue

But I don't want log message to be written in /var/log/messages because I don't have root privileges. Instead I want it to be written to a file in my home directory: /home/myuser/mylog

How should I modify logger command above?

7 Answers 7

10

If you want to use logger so that the message appears both in the system logs and in some file of yours, you might do

  logger -s your message 2> $HOME/somefile

since the -s option to logger also outputs on stderr which is redirected to the file with 2>

You could want to use 2>> $HOME/somefile to append (not overwrite) your $HOME/somefile (read about bash redirections), and (see logger(1) for details) you may prefer to pass the program option --id=$$ to logger.

6
  • How about exitvalue=$? ? where should i insert it above?
    – alwbtc
    Commented Nov 27, 2012 at 20:30
  • @Basile Starynkevitch I use this command, it shows on STDOUT. But it didn't save in the givwn file . Why ?
    – devsda
    Commented Mar 12, 2013 at 19:56
  • 2
    2>&1 redirects stderr to stdout. It will not write to a file unless you redirect stdout to this file too. You can redirect both with > the_file 2>&1 or, if you don't want to save stdout, you can do 2> the_file. I'll edit the answer with the latter. Commented Jan 18, 2014 at 9:44
  • 3
    This works great for me: logger --no-act -s LOG MESSAGE HERE >> test.log 2>&1
    – Kieveli
    Commented May 18, 2017 at 13:57
  • 1
    @Kieveli thanks so much, i was looking for such feature. works great! this way logs won't be duplicated in system Commented Feb 24, 2020 at 17:22
9

I don't think you really need to (or want to) involve logger/syslog for this. Simply replace the last line of the script with:

echo "Exit code of my program is $exitvalue" >> /some/file/that/you/can/write/to
2
  • 1
    Proper timestamping would be lost this way, he'd have to do it manually then. Also, to support priority levels and/or tags (which are very common features of even the most primitive loggers, e.g. differentiating success, error, warning etc.), he'd have to implement, that, too from scratch. (Been there, done that, and after a few halfhearted attempt I just ended up with logger, too.)
    – Sz.
    Commented Jan 14, 2017 at 14:18
  • @Sz. Those observations are all correct. But, aside from customizing the configuration of syslog (or syslog-ng or rsyslog, whatever version his distribution is using), which he can't do without root privilege, rolling your own, possibly with the aid of certain Python/Java/whatever libraries are available, is pretty much the only way to get the logs into a file that you control...
    – twalberg
    Commented Jan 14, 2017 at 15:42
9

The short "official" answer is that, unfortunately, you can't.

However, in most cases (e.g. on many Linux distros) you may just be lucky enough to have a logger implementation that both supports the --no-act option, and also implements some message formatting on its own (see below), in which case you can use a (moderately ugly) command like this to put a) a properly formatted message, b) to a file, c) not polluting the system logs:

logger --no-act -s "Oh dear..." 2>&1 | sed 's/^<[0-9]\+>//' >> /tmp/my.log

(Shout out to @BasileStarynkevitch, and @Kieveli, who both mentioned parts of it before, just not the whole story.)

Notes:

1) To match the usual log file format, I had to "sed off" the <PRIVAL> field (PRIVAL = FACILITY * 8 + PRIORITY) that got prepended to the output on my Debian boxes. Your mileage may vary.

2) POSIX itself does not define how exactly the logger command should treat (any of) its options. E.g. the GNU logger does not support --no-act at all. Also, when posting the original version of this answer 2 years ago, -s on my system did not do any formatting to the printed output, it just echoed the raw message alone, rendering it completely useless. (I didn't use Systemd at that time, which might explain the difference, seeing various conditional Systemd-related calls in the logger source code, but this is just vague guesswork.)

3) The most likely reason why the logger command has been so "historically unfriendly" for this trivial use case is that it's just a fairly simple frontend to the system logger. This means that anything you feed to it basically goes right through to syslogd (or systemd-journald etc.), which, in turn, does all sorts of other further processing, and dispatching (to various outlets: files, sockets etc., both local and remote), as well as bridging permission levels (so in your example you could still log to syslog or user.log, for instance, even though you may have no permission to write to those files directly).

For logger to be able to properly log to a file directly, it would either have to (re)implement some of the duties of the system logger, and the syslog() std. library function, or it would be not much more capable than a trivial echo one-liner (less complex, perhaps, even than the above logger invocation! ;) ). Either way, that seems like a bad idea.

A better solution could be if the POSIX interface (logger, syslog()) had a way to specify an ad-hoc outlet/facility parameter (like a filename) along with the message, so one could log to custom files without reconfiguring the system (which normal users have no permission to do anyway).

However, for the lack of anything better, the "canonical" Linux logger implementation actually does seem to duplicate some of the syslog functionality, so most of us can just enjoy that luxury for free. ;)

5

I think your better choice would be to use the date command rather then logger in cases where you don't want to write to the syslog files (and don't have privs to do so).

See "timestamp before an echo" for details on how to use date to prefix a message with a date and write it to a file.

You create a bash function that looks like the following, adjusting the date format string to get what you want:

echo_time() {
    echo `date +'%b %e %R '` "$@"
}

In your bash script, you would then use:

echo_time "Your message here" >> ${LOGFILE}

Which would put the following in your ${LOGFILE} file:

Mar 11 08:40 your message here
3
$ man logger

Logger provides a shell command interface to the syslog(3) system log module.

You'll need to change your syslog configuration if you want it to log things to other places. You could establish a certain facility that has an output file in your home directory, for example. You would need to be root to do that, though.

0

You can create a small logger function like this on top of your script file:

#! /bin/bash

#LOG FILE location
log_file=/tmp/mylogfile.log

#the LOG function
LOG()
{
time=$(date '+%Y-%m-%d %H:%M:%S')
echo "$time"" >>> "$1 >>${log_file}
}


message= echo "test logger message"
#to send loggers to your log file use
LOG "my message logged to my log file with timestamp = ""$message" 

check output :

head -1 /tmp/mylogfile.log
2019-09-16 14:17:46 >>> my message logged to my log file with timestamp = test logger message
0

I you can use cat - witch echoes your output then >> [file] witch prints the output to [file] inset of terminal so the command would be

cat - >> [file]

the down side is you have to use ctrl+C or ctrl+Z to exit logger is better for online code

Not the answer you're looking for? Browse other questions tagged or ask your own question.