How to Manage Log Verbosity Inside a Shell Script

How do I manage log verbosity inside a shell script?

You already have what seems to be the cleanest idea in your question (a wrapper function), but you seem to think it would be messy. I would suggest you reconsider. It could look like the following (not necessarily a full-fledged solution, just to give you the basic idea) :

#!/bin/bash

# Argument 1 : Logging level for that command
# Arguments 2... : Command to execute
# Output suppressed if command level >= current logging level
log()
{
if
(($1 >= logging_level))
then
"${@:2}" >/dev/null 2>&1
else
"${@:2}"
fi
}

logging_level=2

log 1 command1 and its args
log 2 command2 and its args
log 3 command4 and its args

You can arrange for any required redirection (with file descriptors if you want) to be handled in the wrapper function, so that the rest of the script remains readable and free from redirections and conditions depending on the selected logging level.

Elegant way for verbose mode in scripts?

As you noticed, you can define some log functions like log, log_debug, log_error, etc.

function log () {
if [[ $_V -eq 1 ]]; then
echo "$@"
fi
}

It can help increasing your main code readability and hide show\nonshow logic into logging function.

log "some text"

If _V(global variable) is equal 1 "some text" will be printed, in other case it will not.

Simple logging levels in Bash

One way to approach this is to create an associative array of all the levels. Each level is assigned a number and those numbers are then compared to decide whether you should log or not. Imagine you wanted to add another logging level. Those if statements of yours would get out of control:

#!/usr/bin/env bash

declare -A levels=([DEBUG]=0 [INFO]=1 [WARN]=2 [ERROR]=3)
script_logging_level="INFO"

logThis() {
local log_message=$1
local log_priority=$2

#check if level exists
[[ ${levels[$log_priority]} ]] || return 1

#check if level is enough
(( ${levels[$log_priority]} < ${levels[$script_logging_level]} )) && return 2

#log here
echo "${log_priority} : ${log_message}"
}

logThis "This will log" "WARN"
logThis "This will not log" "DEBUG"
logThis "This will not log" "OUCH"

LOG_PRIORITY_SUPPORTED=false is an example why you should use local variables in functions. Also, you shouldn't use uppercase variables as they could clash with environmental or internal shell variables.

Check current bash verbosity

if [[ $- =~ v ]]; then 
echo "verbose enabled"
else
echo "verbose disabled"
fi

$-: Contains the current set of enabled options. See: help set

How to echo shell commands as they are executed

set -x or set -o xtrace expands variables and prints a little + sign before the line.

set -v or set -o verbose does not expand the variables before printing.

Use set +x and set +v to turn off the above settings.

On the first line of the script, one can put #!/bin/sh -x (or -v) to have the same effect as set -x (or -v) later in the script.

The above also works with /bin/sh.

See the bash-hackers' wiki on set attributes, and on debugging.

$ cat shl
#!/bin/bash

DIR=/tmp/so
ls $DIR

$ bash -x shl
+ DIR=/tmp/so
+ ls /tmp/so
$

linux bash script log output

Thats because, only error from your gzip execution goes into file. To get what you want, use -

mysqldump -u root -p$Pass --all-databases 2>file.log | gzip > fulldbdmp-$(date +%m%d%Y).dump.gz

How to log every single command executed from shell script

I am aware that you were asking for Bash and Shell scripting and tagged your question accordingly, but in respect to your requirements

  • Record every single command that is executed by any user on the system
  • Users are unaware that they are being monitored
  • A solution something at system level

I am under the assumption that you are looking for Audit Logging.

So you may take advantage from articles like

  • Log all commands run by Admins on production servers
  • Log every command executed by a User

How to write Bash Script output to chef-client run

If you're passing a specific verbosity level to knife, it will pass the debug flag to chef client on a bootstrap. Looking at knife's docs, there's:

-V, --verbose: More verbose output. Use twice for max verbosity.

Have you tried passing -VV to knife bootstrap? It should make verbosity = 2, which should trigger passing the debug flag to chef-client during a bootstrap.

For what it's worth, Chef also copies the verbosity setting into Mixlib::CLI's settings. Thus, when you use a bash or execute resource, you should see the output of your bash script within the debug output.

Hope this helps!



Related Topics



Leave a reply



Submit