#885 Issue closed
: Messages on screen missing in log file¶
Labels: enhancement
, cleanup
, fixed / solved / done
jsmeix opened issue at 2016-06-17 13:22:¶
rear master
During
https://github.com/rear/rear/issues/882#issuecomment-226765335
I noticed messages on the screen
that are not logged in the rear log file.
I did "rear -d -D recover" and got this on the screen
(excerpts - long lines wrapped):
RESCUE g130:~ # rear -d -D recover ... Creating filesystem of type btrfs with mount point / on /dev/sda3. 8 bytes [5f 42 48 52 66 53 5f 4d] erased at offset 0x10040 (btrfs) Btrfs v3.18.2+ ATTENTION: mkfs.btrfs is not intended to be used directly. Please use the YaST partitioner to create and manage btrfs filesystems to be in a supported state on SUSE Linux Enterprise systems. Performing full device TRIM (18.38GiB) ... Turning ON incompat feature 'extref': increased hardlink limit per file to 65536 fs created label (null) on /dev/sda3 nodesize 4096 leafsize 4096 sectorsize 4096 size 18.38GiB Mounting filesystem /
But in /var/log/rear/rear-g130.log (in the running recovery system)
there is only (excerpt - long lines wrapped):
+++ LogPrint 'Creating filesystem of type btrfs with mount point / on /dev/sda3.' +++ Log 'Creating filesystem of type btrfs with mount point / on /dev/sda3.' +++ test 1 -gt 0 ++++ Stamp ++++ date '+%Y-%m-%d %H:%M:%S.%N ' +++ echo '2016-06-17 14:42:24.248377595 Creating filesystem of type btrfs with mount point / on /dev/sda3.' 2016-06-17 14:42:24.248377595 Creating filesystem of type btrfs with mount point / on /dev/sda3. +++ Print 'Creating filesystem of type btrfs with mount point / on /dev/sda3.' +++ test -n 1 +++ echo -e 'Creating filesystem of type btrfs with mount point / on /dev/sda3.' +++ mount +++ grep -q /dev/sda3 +++ wipefs -a /dev/sda3 +++ grep -q /dev/sda3 +++ mount +++ mkfs -t btrfs -f /dev/sda3 ++++ grep -o 'uuid: .*' ++++ cut -d : -f 2 ++++ tr -d '[:space:]' ++++ btrfs filesystem show /dev/sda3 +++ new_uuid=56e33393-d7aa-4750-8a41-67a5e8b12fda +++ '[' ffa23495-df2a-4a08-9233-4b84faea5d40 '!=' 56e33393-d7aa-4750-8a41-67a5e8b12fda ']' +++ grep -q ffa23495-df2a-4a08-9233-4b84faea5d40 /var/lib/rear/layout/fs_uuid_mapping grep: /var/lib/rear/layout/fs_uuid_mapping: No such file or directory +++ echo 'ffa23495-df2a-4a08-9233-4b84faea5d40 56e33393-d7aa-4750-8a41-67a5e8b12fda /dev/sda3' +++ LogPrint 'Mounting filesystem /' +++ Log 'Mounting filesystem /' +++ test 1 -gt 0 ++++ Stamp ++++ date '+%Y-%m-%d %H:%M:%S.%N ' +++ echo '2016-06-17 14:42:24.390821545 Mounting filesystem /' 2016-06-17 14:42:24.390821545 Mounting filesystem / +++ Print 'Mounting filesystem /' +++ test -n 1 +++ echo -e 'Mounting filesystem /'
I.e. nothing at all in the log about
Btrfs v3.18.2+ ATTENTION: mkfs.btrfs is not intended to be used directly. Please use the YaST partitioner to create and manage btrfs filesystems to be in a supported state on SUSE Linux Enterprise systems. Performing full device TRIM (18.38GiB) ... Turning ON incompat feature 'extref': increased hardlink limit per file to 65536 fs created label (null) on /dev/sda3 nodesize 4096 leafsize 4096 sectorsize 4096 size 18.38GiB
Perhaps this is a general missing functionality in rear
that everything what appears on the screen is also logged?
@gdha
do you know if everything what appears on the screen
should also be logged when '-d' and '-D' is used
or do I do something wrong?
gdha commented at 2016-06-17 14:29:¶
@jsmeix Try using
https://github.com/gdha/mismas/blob/master/make_rear_diskrestore_script.sh
to generate the disk_restore.sh
(see also
http://www.it3.be/2016/06/08/rear-diskrestore/
for more info).
You will notice that the mkfs commands do not have >&2
appended (I
guess that was done on purpose so that the user see something on the
screen).
jsmeix commented at 2016-06-17 14:41:¶
Do I understand it correctly that only stderr gets into the log
but stdout does not get into the log?
If in usr/sbin/rear the command
exec 2>"$LOGFILE" ...
is the only one that redirects things into the log
then only stderr gets into the log
but stdout stays on the screen.
To get both stdout and stderr on the screen and also in the log
see my scripts in the section
"Generic usage of the plain SUSE installation system for backup and
recovery"
in
https://en.opensuse.org/SDB:Disaster_Recovery
In those scripts I implemeted advanced logging functionality
so that everything what "appears on the screen" is also logged
as follows (excerpts):
# Start logging: my_name=${0##*/} starting_timestamp=$( date +%Y%m%d%H%M%S ) log_file=$my_name.$starting_timestamp.log # Have a new file descriptor 3 which is a copy of the stdout file descriptor: exec 3>&1 # Have a new file descriptor 4 which is a copy of the stderr file descriptor: exec 4>&2 # Have stdout on the terminal and also in the log file: exec 1> >( exec -a $my_name:tee tee -a $log_file ) logging_tee_pid=$! # Make stderr what stdout already is (i.e. terminal and also in the log file): exec 2>&1 ... # Stop logging: # Have stdout and stderr on the terminal but no longer in the log file that is in use by the my_name:tee process # which was forked at "Start logging" via: exec 1> >( exec -a $my_name:tee tee -a $log_file ) # Close stdout and stderr to finish the my_name:tee logging process: exec 1>&- exec 2>&- # Reopen stdout as what was saved in file descriptor 3: exec 1>&3 # Reopen stderr as what was saved in file descriptor 4: exec 2>&4 # Wait one second to be on the safe side that the my_name:tee logging process has finished: sleep 1 if ps $logging_tee_pid 1>/dev/null then echo "$my_name:tee process (PID $logging_tee_pid) still running (writes to $log_file)." echo "Waiting 10 seconds to give the $my_name:tee logging process more time to finish." sleep 10 fi
@gdha
if you like to have such kind of advanced logging functionality
I can work on it to implement that also for rear.
Of course I will use appropriate command line options
so that by default the user does not get zillions of
debug log messages on the screen.
gdha commented at 2016-06-18 07:20:¶
@schlomo would like to see your opinion on this topic as well?
jsmeix commented at 2016-06-21 07:42:¶
To avoid misunderstanding:
I do not plan to change the current behaviour.
My current idea is to add two command line parameters like
Logging: -l have stdout on the terminal and also in the log file -L have stderr in the log file and also on the terminal By default (i.e. without '-l' and/or '-L') stdout is on the terminal and stderr goes to the log file.
schlomo commented at 2017-06-20 12:16:¶
I think it would be nice to also duplicate stdout into the log file. I don't see the additional benefit (beyond us developers) to mirror stderr to the terminal as well. Quite the opposite, for ReaR users it is our job to handle all the error situations either with a meaningful response in our code or by aborting and asking the user to look into the log file.
So, as in any case the logfile is the important source of truth I would
add the stdout to the logfile so that the logfile gives a more complete
picture. If a single command has output on stderr that we prefer on
stdout then for this single command we should redirect the output to
stdout (2>&1
).
As in many other cases, I think that making this configurable adds more complexity for little value. Adding stdout to the log is however valuable to complete the picture in the logfile. BTW, looking at the title of this issue also reminds me to keep it simple and just implement that: screen messages in logfile.
jsmeix commented at 2017-06-20 14:25:¶
@schlomo
I will implement to duplicate stdout into the log file.
I agree that it is sufficient when all is in the log file.
It is not needed to have all on the terminal.
I think duplicating stdout into the log file could be done
in any case even without any additional option.
schlomo commented at 2017-06-20 14:32:¶
Yes, that's what I meant: Simply add all stdout into the logfile by default, that should not be an option.
jsmeix commented at 2017-06-20 14:42:¶
I like it so much that after some discussion
we find simple solutions that "just do the right thing"!
jsmeix commented at 2017-06-21 13:43:¶
Unfortunately it is not so simple as it looks to
"Simply add all stdout into the logfile"
if one wants to keep strict ordering of stdout and stderr outputs.
With
exec 1> >( exec -a $my_name:tee tee -i -a $log_file ) exec 2>>$log_file
one gets stdout on the terminal and also in the log file
and stderr only in the log file (but no longer on the terminal)
but then stdout and stderr outputs that happen at basically
the same time can show up in the opposite order in the log file
(usually stderr gets shown first).
I think the reason is that for stdout there is the 'tee' process
in beween where output is even further delayed by the named pipe
with its buffers that are also in beween compared to stderr
that gets directly appended to the log file.
What would keep the ordering is
exec 1> >( exec -a $my_name:tee tee -i -a $log_file ) exec 2>&1
because with 2>&1 both streams are correctly merged, cf.
https://unix.stackexchange.com/questions/157689/how-to-capture-ordered-stdout-stderr-and-add-timestamp-prefixes
because now bash outputs stdout and stderr both via
the exact same file descriptor (that happens to be a
named pipe with a 'tee' consumer process).
But of course one same file descriptor for stdout and stderr
results that both stdout and stderr appear on the terminal
(and in the log file) and I guess we definitely do not want
stderr on the terminal for "rear -d -D ..." ;-)
BUT:
Usually we also do not want stdout on the terminal,
cf. "What to do with stdout and stderr" in
https://github.com/rear/rear/wiki/Coding-Style
Therefore I wonder now if I should perhaps by default
redirect both stdout and stderr only to the log file
and have both of them no longer on the terminal.
For output that is really meant for the user on the terminal
one could use explicit termial output e.g. via things like
test -w /dev/tty && echo "output for the user" >/dev/tty
or like the Print function does it by explicitly using fd7
as implemented in _input-output-functions.sh
# duplication STDOUT to fd7 to use for Print exec 7>&1 ... function Print () { test "$VERBOSE" && echo -e "${MESSAGE_PREFIX}$*" >&7 || true }
My question is now:
Should I implement stdout on the terminal and also in the log file
and stderr only in the log file (but not on the terminal)
without keeping strict ordering of stdout and stderr outputs
or
should I redirect both stdout and stderr only to the log file
and have both of them no longer on the terminal
(which keeps strict ordering of stdout and stderr outputs
in the log file).
In the latter case I would also have to fix all actually intended
user dialogs via the terminal - in particular all places that
ask the user for input via a generic user input function, cf.
https://github.com/rear/rear/issues/1366
schlomo commented at 2017-06-21 14:06:¶
I think that a first good step is to make sure that all output intended for the screen is generated by a ReaR custom function like Print and not plain echo.
Once that is done we can experiment with global redirects. I am afraid that if we start with global redirects before that then we might end up missing crucial messages.
jsmeix commented at 2017-06-21 14:31:¶
Of course I had meant fixing all actually intended user dialogs
via the terminal as a precondition before redirecting stdout
only to the log file.
But that could be a long task.
Therefore - if you agree - I would like to do the following:
As a first step for now I will implement
duplicating stdout on the terminal and also in the log file
without keeping strict ordering of stdout and stderr outputs.
Then as a second step I will fix all actually intended user messages
and dialogs by using generic ReaR user input/output functions.
Finally as last step (after wating some time for possible bugs)
I would implement redirecting both stdout and stderr
only to the log file.
schlomo commented at 2017-06-21 17:18:¶
@jsmeix I am afraid that adding stdout to the log with wrong ordering will do us more harm than good. It will be extremely confusing to analyze such logs as you will have to guess what belongs where.
jsmeix commented at 2017-06-22 07:56:¶
O.k. then I will do it right from the start:
First as a precondition I will fix all actually intended user messages
and dialogs by using generic ReaR user input/output functions
which means in particular that I will first do
https://github.com/rear/rear/issues/1366
jsmeix commented at 2017-06-22 08:05:¶
@schlomo
I think usually the ordering would not go totally wrong
but only a bit misplaced.
But theoretically the 'tee' process with its named pipe
could delay the stdout output arbitrarily so that it is not
impossible that the ordering gets arbitrarily messed up.
jsmeix commented at 2017-06-22 08:12:¶
FYI
here my stand-alone testing script
cf.
https://github.com/rear/rear/issues/885#issuecomment-226787322
#!/bin/bash my_name=${0##*/} starting_timestamp=$( date +%Y%m%d%H%M%S ) # Start logging: # A side note regarding preserving the ordering of stdout and stderr outputs see # https://stackoverflow.com/questions/12517519/how-to-redirect-stdoutstderr-to-one-file-while-keeping-streams-separate # that states that it is futile to try to preserve ordering because it is impossible # because when there are writes to stderr and stdout that happen basically at the same time # they can show up in the opposite order in the log file and also on the terminal. log_file=$my_name.$starting_timestamp.log # Have a new file descriptor 3 which is a copy of the stdout file descriptor: exec 3>&1 # Have a new file descriptor 4 which is a copy of the stderr file descriptor: exec 4>&2 # Have stdout on the terminal and also in the log file by # redirecting stdout '1>' into a named pipe '>()' running 'tee'. # Using 'tee -i' to avoid that signal interrupts (traps) disrupt stdout in the main script # e.g. if there is a "trap 'echo Exiting' EXIT" and one does [Ctrl]+[C] one will not have "Exiting" in the log file, cf. # https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself exec 1> >( exec -a $my_name:tee tee -i -a $log_file ) logging_tee_pid=$! # Have stderr only in the log file (but no longer on the terminal). # This cannot keeping strict ordering of stdout and stderr outputs. # It is crucial to append to the log file '>>' instead of plain writing to it '>' # because when a program (bash in this case) is plain writing to the log file it can overwrite # output of the simultaneously running 'tee -a' process that appends stdout to the log file # (i.e. with plain '2>$log_file' at least some stdout would be missing in the log file): #exec 2>>$log_file # Make stderr the same what stdout already is (i.e. terminal and also in the log file). # This keeps strict ordering of stdout and stderr outputs # because now both stdout and stderr use one same file descriptor # (that happens to be a named pipe with a 'tee' consumer process): exec 2>&1 # Test logging: trap 'echo Exiting' EXIT for i in $( seq 9 ) do echo "a 1 stdout message $i" echo "a 2 stderr message $i" 1>&2 echo "b 1 stdout message $i" echo "b 2 stderr message $i" 1>&2 test -w /dev/tty && echo "tty sleeping 1 second" >>/dev/tty sleep 1 done # Stop logging: # Have stdout and stderr on the terminal but no longer in the log file that is in use by the my_name:tee process # which was forked at "Start logging" via: exec 1> >( exec -a $my_name:tee tee -i -a $log_file ) # Close stdout and stderr to finish the my_name:tee logging process: exec 1>&- exec 2>&- # Reopen stdout as what was saved in file descriptor 3: exec 1>&3 # Reopen stderr as what was saved in file descriptor 4: exec 2>&4 # Wait one second to be on the safe side that the my_name:tee logging process has finished: sleep 1 if ps $logging_tee_pid 1>/dev/null then echo "$my_name:tee process (PID $logging_tee_pid) still running (writes to $log_file)." echo "Waiting 10 seconds to give the $my_name:tee logging process more time to finish." sleep 10 fi
jsmeix commented at 2017-06-22 14:05:¶
Only an intermediate info:
I am currently experimenting with this in usr/sbin/rear
to get both STDOUT and STDERR into the log file:
# Source usr/share/rear/lib/_input-output-functions.sh because therein # the original STDOUT and STDERR file descriptors are saved as fd7 and fd8 # so that ReaR functions for actually intended user messages can use fd7 and fd8 # to show messages to the user regardless whereto STDOUT and STDERR are redirected: source $SHARE_DIR/lib/_input-output-functions.sh # Keep old log file: test -r "$RUNTIME_LOGFILE" && mv -f "$RUNTIME_LOGFILE" "$RUNTIME_LOGFILE".old 2>/dev/null # Start logging: mkdir -p $LOG_DIR || echo "ERROR: Could not create $LOG_DIR" >&2 cat /dev/null >"$RUNTIME_LOGFILE" # Redirect both STDOUT and STDERR into the log file: exec 2>>"$RUNTIME_LOGFILE" exec 1>&2 # Include functions after RUNTIME_LOGFILE is set and readonly # so that functions can use a fixed RUNTIME_LOGFILE value: for script in $SHARE_DIR/lib/[a-z]*.sh ; do source $script done
With this I get "interesting" looking results:
Now some scripts spit out error messages on the terminal
regardless that STDOUT and STDERR should go to the log file.
It seems there is much to do and to clean up
until also redirecting STDOUT works properly.
It seems parts of ReaR somehow depend
on STDOUT not being redirected.
I think ReaR should work properly regardless whereto
STDOUT and STDERR might be redirected because
I think it must be possible that the user calls 'rear' from
within any environment with any STDOUT and STDERR
redirections set up by the user as he likes it (e.g. for
whatever automated use case like via cron or whatever).
I think having by default STDOUT and STDERR redirected
into the log file is only one particular use case.
jsmeix commented at 2017-06-22 14:16:¶
Found a first easy explanation why error messages
appear unexpectedly on the terminal.
It is the old deprecated usage of '>&8'
e.g. as in prep/GNU/Linux/200_include_serial_console.sh
for devnode in $(ls /dev/ttyS[0-9]* | sort); do if stty -F $devnode >&8 2>&1; then USE_SERIAL_CONSOLE=y fi done
because now with my new _input-output-functions.sh
the original STDOUT and STDERR file descriptors
are now saved as fd7 and fd8 so that all what is sent to fd8
appears on the original STDERR which is the terminal.
I was already aware of it that I also have
to fix all the old deprecated usage of '>&8'
and if that is all, it is easy - much to do but easy.
I look forward to finally get all that old stuff cleaned up!
jsmeix commented at 2017-06-22 14:23:¶
I.e. solving
https://github.com/rear/rear/issues/887
is another precondition for this issue here.
jsmeix commented at 2017-06-26 12:26:¶
With
https://github.com/rear/rear/pull/1391
merged
this issue should be already solved regardless
that
https://github.com/rear/rear/issues/887
is not yet solved, for an explanation why see
https://github.com/rear/rear/pull/1391#issuecomment-311040948
jsmeix commented at 2017-06-26 12:45:¶
In
https://github.com/rear/rear/wiki/Coding-Style
I explained "What to do with stdout and stderr" when
both stdout and stderr are redirected into ReaR's log file.
jsmeix commented at 2017-06-28 14:29:¶
The redirection of STDOUT into the log file can
cause regressions when interactive tools are "just called",
see
https://github.com/rear/rear/issues/1398
jsmeix commented at 2017-07-19 09:03:¶
I reopen this issue because the
redirection of STDOUT into the log file
will not happen for ReaR v 2.2.
Because ReaR v 2.2 was preponed, cf.
https://github.com/rear/rear/issues/1398#issuecomment-315318878
I postponed the redirection of STDOUT vor ReaR v 2.2 in
https://github.com/rear/rear/commit/f47f705c0857e46b93c2ccc49b8ba504c05559eb
cf.
https://github.com/rear/rear/issues/1398#issuecomment-315325470
jsmeix commented at 2017-10-20 10:01:¶
For ReaR v2.3 redirection of stdout into the log file is re-enabled
via
https://github.com/rear/rear/commit/6ab3c4173fe425bb018880af4a8461bf575ba1e0
so that this issue is fixed for ReaR v 2.3.
jsmeix commented at 2018-05-18 08:56:¶
An addedum regarding the above
https://github.com/rear/rear/issues/885#issuecomment-310308763
that reads
# It is crucial to append to the log file '>>' instead of plain writing to it '>' # because when a program (bash in this case) is plain writing to the log file it can overwrite # output of the simultaneously running 'tee -a' process that appends stdout to the log file # (i.e. with plain '2>$log_file' at least some stdout would be missing in the log file):
here an example command that shows how append to one same log file works:
{ of=/tmp/out ; cat /dev/null >$of ; \ ( for i in $( seq 10 29 ) ; do echo "i=$i" ; cat i=$i ; done 1>>$of 2>&1 ) & \ ( for j in $( seq 10 29 ) ; do echo "j=$j" ; cat j=$j ; done 1>>$of 2>&1 ) & \ wait ; \ echo $( grep -o 'i=..' $of | wc -l ) i messages ; \ echo $( grep -o 'j=..' $of | wc -l ) j messages ; \ cat -n $of ; } | less
that results e.g. this output
40 i messages 40 j messages 1 i=10 2 j=10 3 cat: 'i=10': No such file or directory 4 cat: 'j=10': No such file or directory 5 i=11 6 j=11 7 cat: 'i=11': No such file or directory 8 cat: 'j=11': No such file or directory 9 i=12 10 j=12 11 cat: 'i=12': No such file or directorycat: 12 'j=12': No such file or directory 13 i=13 14 j=13 15 cat: 'i=13'cat: 'j=13': No such file or directory: No such file or directory 16 17 j=14 18 i=14 19 cat: 'i=14'cat: 'j=14': No such file or directory 20 : No such file or directory 21 i=15 22 j=15 23 cat: 'j=15'cat: 'i=15': No such file or directory 24 : No such file or directory 25 j=16 26 i=16 27 cat: 'j=16'cat: 'i=16': No such file or directory 28 : No such file or directory 29 j=17 30 i=17 31 cat: 'j=17': No such file or directory 32 cat: 'i=17': No such file or directory 33 j=18 34 i=18 35 cat: 'j=18': No such file or directory 36 cat: 'i=18': No such file or directory 37 j=19 38 i=19 39 cat: 'j=19'cat: 'i=19': No such file or directory 40 : No such file or directory 41 j=20 42 i=20 43 cat: 'i=20': No such file or directory 44 cat: 'j=20': No such file or directory 45 i=21 46 j=21 47 cat: 'i=21': No such file or directory 48 cat: 'j=21': No such file or directory 49 i=22 50 j=22 51 cat: 'i=22': No such file or directory 52 cat: 'j=22'i=23 53 : No such file or directory 54 j=23 55 cat: 'i=23': No such file or directory 56 cat: 'j=23': No such file or directory 57 i=24 58 j=24 59 cat: 'j=24'cat: 'i=24': No such file or directory 60 : No such file or directory 61 j=25 62 i=25 63 cat: 'i=25': No such file or directory 64 cat: 'j=25': No such file or directory 65 i=26 66 j=26 67 cat: 'i=26': No such file or directory 68 cat: 'j=26': No such file or directory 69 i=27 70 j=27 71 cat: 'j=27'cat: 'i=27': No such file or directory 72 : No such file or directory 73 j=28 74 i=28 75 cat: 'j=28': No such file or directory 76 j=29 77 cat: 'i=28': No such file or directory 78 i=29 79 cat: 'j=29': No such file or directory 80 cat: 'i=29': No such file or directory
Message lines of the two simultaneously running processes can get
intermixed
but on the other hand all output of the two processes appears in the log
file and
all output appears in the exact right chronological ordering
(which is the reason why message lines get intermixed).
[Export of Github issue for rear/rear.]