How can I pass argument to a Bash script for 'tee'? - linux

I want to create a log output file based on the arguments I pass. I tried the below, which didn't work.
#!/bin/bash
echo "hello" | tee -a log_$1.log
I want a log_test.log to be created, instead log_.log is created:
./script test

Using ${1} would resolve the issue.
#!/bin/bash
echo "hello" | tee -a log_${1}.log

Related

Linux bash script: share variable among terminal windows

If I do this:
#!/bin/bash
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty);
echo $VAR1; bash'
echo $VAR1
How can I get the last line from this script to work? I.e., be able to access the value of $VAR1 (stored on the new terminal window) from the original one? Currently, while the first echo is working, the last one only outputs an empty line.
The short version is that you can't share the variable. There's no shared channel for that.
You can write it to a file/pipe/etc. and then read from it though.
Something like the following should do what you want:
#!/bin/bash
if _file=$(mktemp -q); then
gnome-terminal --window-with-profile=KGDB -x bash -c 'VAR1=$(tty); echo "$VAR1"; declare -p VAR1 > '\'"$_file"\''; bash'
cat "$_file"
. "$_file"
echo "$VAR1"
fi

How can I get the command that was executed at the command line?

If I call a script this way:
myScript.sh -a something -b anotherSomething
Within my script is there a way to get the command that called the script?
In my script on the first line I'm trying to use:
lastCommand=!!
echo $lastCommand
But the result is always null.
If I do echo !! the only thing that prints to the console is !!, but from the command line if I do echo !! I get the last command printed.
I've also tried:
echo $BASH_COMMAND
but I'm getting null here as well. Is it because the script is called in a subshell and thus there is no previous command stored in memory for the subshell?
The full command which called the script would be "$0" "$#", that is, the command itself followed by all the arguments quoted. This may not be the exact command which was run, but if the script is idempotent it can be run to get the same result:
$ cat myScript.sh
#!/usr/bin/env bash
printf '%q ' "$0" "$#"
printf '\n'
$ ./myScript.sh -a "foo bar" -b bar
./myScript.sh -a foo\ bar -b bar
Here's my script myScript.sh
#!/bin/bash
temp=`mktemp`
ps --pid $BASHPID -f > $temp
lastCommand=`tail -n 1 $temp | xargs | cut -d ' ' -f 8-`
rm $temp
echo $lastCommand
or
#!/bin/sh
last=`cat /proc/$$/cmdline | xargs -0`
echo $last

Shell script to log output of console

I want to grep the output of my script - which itself contains call to different binaries...
Since the script has multiple binaries within I can't simply put exec and dump the output in file (it does not copy output from the binaries)...
And to let you know, I am monitoring the script output to determine if the system has got stuck!
Why don't you append instead?
mybin1 | grep '...' >> mylog.txt
mybin2 | grep '...' >> mylog.txt
mybin3 | grep '...' >> mylog.txt
Does this not work?
#!/bin/bash
exec 11>&1 12>&2 > >(exec tee /var/log/somewhere) 2>&1 ## Or add -a option to tee to append.
# call your binaries here
exec >&- 2>&- >&11 2>&12 11>&- 12>&-

Bash Script : Unwanted Output

I have this simple bash script:
I run ns simulator on each file passed in argument where last argument is some text string to search for.
#!/bin/bash
nsloc="/home/ashish/ns-allinone-2.35/ns-2.35/ns"
temp="temp12345ashish.temp"
j=1
for file in "$#"
do
if [ $j -lt $# ]
then
let j=$j+1
`$nsloc $file > $temp 2>&1`
if grep -l ${BASH_ARGV[0]} $temp
then
echo "$file Successful"
fi
fi
done
I expected:
file1.tcl Successful
I am getting:
temp12345ashish.temp
file1.tcl Successful
When i run the simulator command myself on the terminal i do not get the file name to which output is directed.
I am not getting from where this first line of output is getting printed.
Please explain it.
Thanks in advance.
See man grep, and see specifically the explanation of the -l option.
In your script (above), you are using -l, so grep is telling you (as instructed) the filename where the match occurred.
If you don't want to see the filename, don't use -l, or use -q with it also. Eg:
grep -ql ${BASH_ARGV[0]} $temp
Just silence the grep:
if grep -l ${BASH_ARGV[0]} $temp &> /dev/null

Force `tee` to run for every command in a shell script?

I would like to have a script wherein all commands are tee'd to a log file.
Right now I am running every command in the script thusly:
<command> | tee -a $LOGFILE
Is there a way to force every command in a shell script to pipe to tee?
I cannot force users to add appropriate teeing when running the script, and want to ensure it logs properly even if the calling user doesn't add a logging call of their own.
You can do a wrapper inside your script:
#!/bin/bash
{
echo 'hello'
some_more_commands
echo 'goodbye'
} | tee -a /path/to/logfile
Edit:
Here's another way:
#!/bin/bash
exec > >(tee -a /path/to/logfile)
echo 'hello'
some_more_commands
echo 'goodbye'
Why not expose a wrapper that's simply:
/path/to/yourOriginalScript.sh | tee -a $LOGFILE
Your users should not execute (nor even know about) yourOriginalScript.sh.
Assuming that your script doesn't take a --tee argument, you can do this (if you do use that argument, just replace --tee below with an argument you don't use):
#!/bin/bash
if [ -z "$1" ] || [ "$1" != --tee ]; then
$0 --tee "$#" | tee $LOGFILE
exit $?
else
shift
fi
# rest of script follows
This just has the script re-run itself, using the special argument --tee to prevent infinite recursion, piping its output into tee.
Some approach would be creation of runner script "run_it" that all users invoke their own scripts.
run_it my_script
All the magic would be done within, e.g. could look like that:
LOG_DIR=/var/log/
$# | tee -a $LOG_DIR/

Resources