bash script for man with custom output - bash

I'm trying to do a bash script which gives me only the first line of man for "n" commands.
example:
$ sh ./start.sh ls wazup top
ls - list directory contents
wazup - manpage does not exist
top - display Linux tasks
This is my current code:
! bin/bash/
while [ -n "$1" ]
do
which $1> /dev/null
man $1 | head -6 | tail -1
if [ $? = 0 ]
then
echo "manpage does not exist"
fi
shift
done
My Output is:
ls - list directory contents
manpage does not exist
No manual entry for wazzup
manpage does not exist
top - display Linux processes
manpage does not exist

Check the status code returned by man, not once it's piped through head and tail (which will be wrong as it will be the return status of tail).

Many Thanks Alex!
Solved it by not using pipes with your help! :)
Here's my final code for anyone that needs it:
#!/bin/bash
while [ -n "$1" ]
do
which $1> /dev/null
if [ $? = 0 ]
then
man -f $1
else
echo "$1: manpage does not exist"
fi
shift
done

Related

ps command in sh script not include the top command

I have written a script to check process is running or not,it work fine but while testing it, i have found that it not include top command count running in other terminal
check-process.sh
#!/bin/sh
OK=1
CRITICAL=0
PROCESS_NUM=$( ps -ef | grep $1 | grep -v "grep "|grep -v "sh"|wc -l )
#echo $PROCESS_NUM
if [ $PROCESS_NUM = $OK ]
then
echo "OK"
elif [ $PROCESS_NUM = $CRITICAL ]
then
echo "CRITICAL"
elif [ $PROCESS_NUM > $OK ]
then
echo "MULTIPLE process are runing"
else
echo "error"
fi
And i run top command in two terminals and run this script as follow:
./check-process.sh top
and out put is 0 CRITICAL , but when i run normal command ps -ef |grep -v "grep "| wc -l it gives two counts.
That mess of greps just has to go.
One "trick" for finding processes by name without finding your grep is to use a regular expression. That is, after all, what the Global Regular Expression Print command is for. You can use parameter expansion to construct a safe regular expression based on your input string, perhaps like this:
#!/bin/sh
if [ -z "$1" ]; then
echo "I'd love me an option." >&2
exit 1
fi
OK=1
CRITICAL=0
x="${1#?}" # make a temporary string missing the 1st chararcter,
re="[${1%$x}]$x" # then place the 1st character within square brackets.
PROC_COUNT=$( ps -ef | grep -w -c "$re" ) # yay, just one pipe.
if [ "$PROC_COUNT" -eq "$OK" ]; then
echo "OK"
elif [ "$PROC_COUNT" -eq "$CRITICAL" ]; then
echo "CRITICAL"
elif [ "$PROC_COUNT" -gt "$OK" ]; then
echo "MULTIPLE process are running"
else
echo "error"
fi
There are a few notable changes here:
I added something to fail with better explanation if no option is given.
The pipeline, of course. And the lines that create $re.
We're using -gt and -eq to test numeric values. man test for details.
I renamed your count variable to be clearer. What is a "PROCESS_NUM" really? Sounds like a PID to me.
All variables are quoted. I don't need to tell you why, you have the Google.
That said, you should also consider using pgrep instead of any sort of counting pipe, if it's available on your system. Try running pgrep and see what your OS tells you.

Grep issues with if statement in shell script

I'm having an issue with tail & grep in shell script if statement. If I run tail -5 mylog.log | grep -c "Transferred: 0" in shell, it runs as it should, but in this shell script if statement:
# Parse log for results
if [ tail -1 "$LOGFILE" | grep -c "Failed" ] ; then
RESULT=$(tail -1 "$LOGFILE")
elif [ tail -5 "$LOGFILE" | grep -c "Transferred: 0" ] ; then
RESULT=""
else
RESULT=$(tail -5 "$LOGFILE")
fi
I get
... [: missing `]'
grep: ]: No such file or directory
for both of the grep lines.
It's clearly to do with the closing ] being seen as part of the grep (and thus missing) but I'm using the correct whitespace so I can't figure out what's going on? What am I doing wrong here?
Thanks,
PJ
Immediate Issue / Immediate Fix
Take out the brackets.
if tail -1 "$logfile" | grep -q "Failed" ; then
[ is not part of if syntax. Rather, it's a synonym for the command named test (which is typically both available as a shell builtin and an external binary, like /bin/test or /usr/bin/test).
Thus, your original code was running [ tail -1 "$logfile", and piping its result to grep -q "Failed" ]. The first [ was failing because it didn't see an ending ] -- which is mandatory when invoked by that name rather than with the name test -- and also because its parameters weren't a test it knew how to parse; and the second grep didn't know what the ] it was being piped meant, trying to find a file by that name.
Other Notes
Try to run external commands -- like tail -- as little as possible. There's a very significant startup cost.
Consider the following, which runs tail only once:
#!/bin/bash
# ^^^^- IMPORTANT: bash, not /bin/sh
last_5_lines="$(tail -5 "$logfile")"
last_line="${last_5_lines##*$'\n'}"
if [[ $last_line = *Failed* ]]; then
result=$last_line
elif [[ $last_5_lines =~ 'Transferred:'[[:space:]]+'0' ]]; then
result=''
else
result=$last_5_lines
fi

Bash: How can I check the return value of a command

I am new to bash scripting and want to write a short script, that checks if a certain program is running. If it runs, the script should bring the window to the foreground, if it does not run, the script should start it.
#!/bin/bash
if [ "$(wmctrl -l | grep Wunderlist)" = ""]; then
/opt/google/chrome/google-chrome --profile-directory=Default --app-id=ojcflmmmcfpacggndoaaflkmcoblhnbh
else
wmctrl -a Wunderlist
fi
My comparison is wrong, but I am not even sure what I should google to find a solution. My idea is, that the "$(wmctrl -l | grep Wunderlist)" will return an empty string, if the window does not exist. I get this error when I run the script:
~/bin ยป sh handle_wunderlist.sh
handle_wunderlist.sh: 3: [: =: argument expected
You need a space before the closing argument, ], of the [ (test) command:
if [ "$(wmctrl -l | grep Wunderlist)" = "" ]; then
....
else
....
fi
As a side note, you have used the shebang as bash but running the script using sh (presumably dash, from the error message).
Replace:
if [ "$(wmctrl -l | grep Wunderlist)" = ""]; then
With:
if ! wmctrl -l | grep -q Wunderlist; then
grep sets its exit condition to true (0) is a match was found and false (1) if it wasn't. Because you want the inverse of that, we placed ! at the beginning of the command to invert the exit code.
Normally, grep will send the matching text to standard out. We don't want that text, we just want to know if there was a match or not. Consequently, we added the -q option to make grep quiet.
Example
To illustrate the use of grep -q in an if statement:
$ if ! echo Wunderlist | grep -q Wunderlist; then echo Not found; else echo Found; fi
Found
$ if ! echo Wunderabcd | grep -q Wunderlist; then echo Not found; else echo Found; fi
Not found

How to terminate a cat pipe command in shell script?

I use a command like to cat a pipe file and grep some data. A simple code such as,
temp=""
temp=$(cat file|grep "some data"| wc -c)
if [ $temp -gt 0 ]
then
echo "I got data"
fi
The file is a pipe(FIFO), it will output data and not stop. How can i to terminate the command of cat pipe in a finite time?
grep|wc is the wrong tool for this job. Choose a better one, such as sed,
if sed -n -e '/some data/q;$q1' file; then
....
fi
awk,
found=$(awk '/some data/{print"y";exit}' file)
if [ -n "$found" ]; then
....
fi
or sh itself.
found=
while read line; do
if expr "$line" : ".*some data" >/dev/null; then
found=y
break
fi
done <file
if [ -n "$found" ]; then
....
fi
I got it adding $ to temp variable in line 3:
if [ $temp -gt 0 ]
Because you want to compare temp value, and you get it using $ before the variable.
About file "pipe", you can execute cat until you get a specific string.
I mean, you can use cat for reading and stop when you receive, for example, a "\n".
I will give you an example that you can run in your terminal:
cat > example_file.txt << EOF
hello
I'm a example filen
EOF
cat will be reading from standard input untill you enter "EOF". And then, the content of the file will be:
cat example_file.txt
hello
I'm an example file
So this way you can read by chunks, for example, lines.
Just check the exit status of grep itself:
if grep -q "some data" file; then
echo "I got data"
fi
The -q prevents anything from being written to standard output if a match is found.
Another way to do it is by using shell script.
cat <some file and conditions> &
< perform your task>
kill $(pidof cat)
This works as long as you have one instance of "cat" running at a time.
You can use timeout command, which is part of coreutils.
man timeout:
NAME
timeout - run a command with a time limit
SYNOPSIS
timeout [OPTION] DURATION COMMAND [ARG]...
...
To wait 10 seconds:
temp=$(timeout 10 cat file|grep "some data"| wc -c)
if [ $temp -gt 0 ]
then
echo "I got data"
fi

Check the output of a command in shell script

I'm writing a very simple shell scripts that would looked at the log of all failed tests, and print out all the name of all files in the current directory that are in the log
1 #! /bin/sh
2 for file in *
3 do
4 echo "checking: $file"
5 if [$(grep $file failed.txt -c) -ne 0]
6 then
7 echo "$file FAILED"
8 fi
9 done
When I execute it, I get this error:
line 6: [0: command not found
Does anyone have any idea why?
Thanks!!
[ is actually a command in linux (like bash or cat or grep).
$(grep $file failed.txt -c) is a command substitution which in your case evaluated to 0. Thus the line now reads [0 -ne 0], which is interpreted as run a program called [0 with arguments -ne 0].
What you should write instead is [ $(grep $file failed.txt -c) -ne 0 ]. Shell scripts require that there be spaces between the opening and closing square braces. Otherwise you change the command that is executed (the closing ] indicates that there are no more arguments to be read.
So now the command evaluates to [ 0 -ne 0 ]. You can try executing this in your shell to see what happens. [ exits with a value of 0 if the expression is true and 1 if it is false. You can see the exit value by echoing $? (the exit value of the last command to be run).
Instead of testing the count, you can test the return code of grep:
if grep -q $file failed.txt &>/dev/null
The script can be
#!/bin/sh
for file in *; do
echo "checking: $file"
grep failed.txt $file && echo "$file FAILED"
done
or, as an one-liner in user shell command history:
for file in *; do { echo "checking: $file" && grep failed.txt $file && echo "$file FAILED"; done
in man grep
EXIT STATUS
The exit status is 0 if selected lines are found, and 1 if not found. If an error occurred the exit status is 2. (Note: POSIX error handling code should check for '2' or greater.)

Resources