Multiple conditions in Bash for outputting error - bash

My question is similar to ones asked multiple times before. I have a script that checks multiple variables on a machine and logs that data. For instance, I'm checking Firewall and Encryption on the machine, and if one or both of them are off I need to echo exactly what is turned off. I'm looking at using something along the lines of this...
if [ $firewall -eq "Off" ] || [ $Encryption -eq "Off" ]; then
echo Please fix ****
else
echo "Everything is great"
fi
I'm having a problem of how parse out the data in the second line.
EDIT: I've gotten some great answers, but the thing I'm curious about is, how would I work it if I have a list of 5 things I'm checking on, and say 2 of them are not meeting the standard. I'd like to output only those that are not passing to the end user so they know what they need to fix?
So given the example above, let's say I'm testing for Firewall, Encryption, Patches, and Disk Space. If the user needs to fix Firewall and Encryption, I'd like to output only those two. If another user has issues with Disk Space, one one to them, and another user has everything okay, then a message that everything is fine.
EDIT 2:* I'm pulling the information I require, the only problem is I need to have one of two different pop-up windows. Either one that shows what exactly is wrong, and that could be any number of things, or one that shows that everything is working properly.
So far I've come up with the code below, but it's showing me two windows, one that shows the errors, and the other "Everything is great" pop-up in that order. Where am I going wrong?
for i in Software Firewall XProtect; do
if [[ "${!i}" == "Off" ]]; then
osascript -e 'tell app "System Events" to display dialog "Compliance Check results \r \r'$i' needs attention\r \rPress OK to continue."'
Elseif
osascript -e 'tell app "System Events" to display dialog "Compliance Check results \r \rEverything looks good. \r \rPress OK to continue."'
fi
done
Thank you in advance for all the help.

-eq is used for Integer comparison only.
Better to simplify your code like this:
if [ "$firewall" = "Off" ]; then
echo "firewall is Off"
elif [ "$Encryption" = "Off" ]; then
echo "Encryption is Off"
else
echo "Everything is great"
fi
EDIT: To check multiple variable you can use this for loop:
for i in A B C D; do
[[ "${!i}" == "Off" ]] && echo "$i is Off"
done

try this
if [[ ${firewall:-} = "Off" || ${Encryption:-} = "Off" ]]; then
echo Please fix ****
else
echo "Everything is great"
fi

Related

Bash output to same line while preserving column

Ok, this is going to seem like a basic question at first, but please hear me out. It's more complex than the title makes it seem!
Here is the goal of what I am trying to do. I would like to output to console similar to Linux boot.
Operating system is doing something... [ OK ]
Now this would seem to be obvious... Just use printf and set columns. Here is the first problem. The console needs to first print the action
Operating system is doing something...
Then it needs to actually do the work and then continue by outputting to the same line with the [ OK ].
This would again seem easy to do using printf. Simply do the work (in this case, call a function) and return a conditional check and then finish running the printf to output either [ OK ] or [ FAIL ]. This technically works, but I ran into LOTS of complications doing this. This is because the function must be called inside a subshell and I cant pass certain variables that I need. So printf is out.
How about just using echo -n? That should work right? Echo the first part, run the function, then continue echoing based on the return to the same line. The problem with this solution is I can no longer preserve the column formatting that I can with printf.
Operating system is doing something... [ OK ]
Operating system is doing something else... [ OK ]
Short example... [ OK ]
Any suggestions how I can fix any of these problems to get a working solution? Thanks
Here is another way I tried with printf. This gives the illusion of working, but the method is actually flawed because it does not give you the progress indication, ie the function runs first before it ever prints out the the function is running. The "hey im doing stuff" prints immediately with the "hey im done" message. As a result, its pointless.
VALIDATE $HOST; printf "%-50s %10s\n" " Validating and sanitizing input..." "$(if [ -z "$ERROR" ]; then echo "[$GREEN OK $RESET]"; else echo "[$RED FAIL $RESET] - $ERROR"; echo; exit; fi)"
There's no particular reason all the printf strings have to be printed together, unless you're worried some code you call is going to move the cursor.
Reordering your example:
printf "%-50s " " Validating and sanitizing input..."
VALIDATE $HOST
if [ -z "$ERROR" ]; then
printf "%10s\n" "[$GREEN OK $RESET]";
else
printf "%10s\n" "[$RED FAIL $RESET] - $ERROR"
echo
exit
fi
I have no idea what $ERROR contains or where it is supposed to display.

Bash script sometimes works, sometimes doesn't... pipes issue

I have a weird situation where Bash doesn't seem to be assigning one of my variables correctly, or it might be to do with pipes. I'm honestly not sure. Here's the code:
test=0
if [ "$#" -ne 4 ]; then
echo "Error: You have passed an incorrect number of parameters" > client.pipe
test=1
if [ $test -eq 1 ]; then <-------THIS SOMETIMES DOESN'T EXECUTE
echo "end_result" > client.pipe
exit 1
What's going on here is this is a server script for a command: 'select'.
The select command takes in 4 parameters: an id (to tell it which pipe to output messages to), a database name, a table name, and then a string of column ids.
At the other end of the client pipe, the client script is listening for messages, and if it receives 'end_result' it stops listening. As you can see, no matter what happens 'end_result' should get sent back to the pipe and printed by the client script, but sometimes it doesn't happen, and I get stuck in an infinite while loop. Here's the client script so you can see where the 'listening' is happening.
while true; do
read message < client.pipe
if [ "$message" == "end_result" ]; then
echo $message
break
else
echo $message
fi
done
If I pass in the incorrect number of parameters to the first script, it prints out 'Error: you have passed an incorrect num of parameters' to the pipe, but then sometimes it doesn't assign 1 to test, and it doesn't then send 'end_result' to the pipe and exit. I can't really see what the issue is, and as I've said it works probably 7 times out of 10... I can get around the issue by having the parent script send 'end_result' to the client, but it's a bit of a hack.
I'd really appreciate it if anyone could see what the issue is, and I'm happy to provide more info about the code if required.
Many thanks, R
EDIT:
I'm almost certain the problem is to do with reading from the client pipe and that while loop, as though something were getting stuck in the pipe...
This was the solution, provided by #WilliamPursell:
while true; do
read message
if [ "$message" == "end_result" ]; then
echo $message
break
else
echo $message
fi
done < client.pipe

Creating a 'yes' or 'no' menu in UNIX bash shell scripting

I'm currently writing a script, and at one point I want it check if a file already exists. If the file doesn't exist, then it should do nothing. However, if the file does exist, I want a 'y' or 'n' (yes or no) menu to appear. It should ask "Do you want to overwrite this file?".
So far I've tried writing something similar to this. Take into account that before this a function called:
therestore
exists. I want this function to occur if they type "y". Anyway, this is what I tried:
If [ -f directorypathANDfilename ] ; then
read -p "A file with the same name exists, Overwrite it? Type y/n?" yesorno
case $yesorno in
y*) therestore ;;
n*) echo "File has not been restored" ;;
esac
fi
For some reason though, the menu always pops up, even if the file DOESN'T exist and it doesn't restore it properly if I type yes! (But I know the "therestore" function works fine, because I've tested it plenty of times).
Apologies for the long-winded question. If you need any more details let me know - thanks in advance!
Does your script even run? Doesn't look like valid bash-script to me. If is not a valid keyword, but if is. Also, tests go inside angle-brackets [ ], those are not optional. Moreover you forgot the closing fi.
And another thing, it's not quite clear to me what you're testing for. Is directorypathANDfilename a variable? In that case you have to reference it with the $.
The snippet would probably work better like this:
#!/bin/bash
if [ -f "$directorypathANDfilename" ] ; then
read -p "A file with the same name exists, Overwrite it? Type y/n?" yesorno
case "$yesorno" in
y*) therestore ;;
n*) echo "File has not been restored" ;;
esac
fi

Bash if statement which saves variable to config file doesn't work

This is my code:
alias radio='
if [ -e "$station" ]
then
open $station
else
say "I still don't know what your favorite radio station is sir. Would you mind giving me the link?"
echo "What is the link of your favorite station?"
read station
echo "station="$station"" >> ~/.fis/config
say "You can now try the command again."
fi'
The code runs up to the part where it asks for the link. When I provide it with a link I get the following error:
-bash: station=http://www.cidadefm.iol.pt/player/player.html?: No such file or directory
Does anyone have any idea of what might be wrong?
WhatsWrongWithMyScript.com helpfully points out that the apostrophe in "don't" is terminating the single quoted expression. Instead of fixing this by using "don'\''t", please use a function instead:
radio() {
if [ -e "$station" ]
then
open $station
else
say "I still don't know what your favorite radio station is sir. Would you mind giving me the link?"
echo "What is the link of your favorite station?"
read station
echo "station=\"$station\"" >> ~/.fis/config
say "You can now try the command again."
fi
}
The main problem is that you are using $station outside of quotes. There's probably an & breaking up the command.
You seem to use the "station" variable name for two different purposes. That's confusing.
Also, kind of awkward to put all that into an alias. I'd use a function
radio () {
local file=~/.fis/config
if [ -f "$file" ]
then
station=$(< "$file")
else
say "I still don't know what your favorite radio station is sir. Would you mind giving me the link?"
echo "What is the URL of your favorite station?"
read staton
echo "$station" > "$file"
fi
open "$station"
}

How to parametrize verbosity of debug output (BASH)?

During the process of writing a script, I will use the command's output in varying ways, and to different degrees - in order to troubleshoot the task at hand.. For example, in this snippet, which reads an Application's icon resource and returns whether or not it has the typical .icns extension...
icns=`defaults read /$application/Contents/Info CFBundleIconFile`
if ! [[ $icns =~ ^(.*)(.icns)$ ]]; then
echo -e $icns "is NOT OK YOU IDIOT! **** You need to add .icns to "$icns"."
else
echo -e $icns "\t Homey, it's cool. That shits got its .icns, proper."
fi
Inevitably, as each bug is squashed, and the stdout starts relating more to the actual function vs. the debugging process, this feedback is usually either commented out, silenced, or deleted - for obvious reasons.
However, if one wanted to provide a simple option - either hardcoded, or passed as a parameter, to optionally show some, all, or none of "this kind" of message at runtime - what is the best way to provide that simple functionality? I am looking to basically duplicate the functionality of set -x but instead of a line-by rundown, it would only print the notifications that I had architected specificically.
It seems excessive to replace each and every echo with an if that checks for a debug=1|0, yet I've been unable to find a concise explanation of how to implement a getopts/getopt scheme (never can remember which one is the built-in), etc. in my own scripts. This little expression seemed promising, but there is very little documentation re: 2>$1 out there (although I'm sure this is key to this puzzle)
[ $DBG ] && DEBUG="" || DEBUG='</dev/null'
check_errs() {
# Parameter 1 is the return code Para. 2 is text to display on failure.
if [ "${1}" -ne "0" ]; then
echo "ERROR # ${1} : ${2}"
else
echo "SUCESSS "
fi }
Any concise and reusable tricks to this trade would be welcomed, and if I'm totally missing the boat, or if it was a snake, and it would be biting me - I apologize.
One easy trick is to simply replace your "logging" echo comamnd by a variable, i.e.
TRACE=:
if test "$1" = "-v"; then
TRACE=echo
shift
fi
$TRACE "You passed the -v option"
You can have any number of these for different types of messages if you wish so.
you may check a common open source trace library with support for bash.
http://sourceforge.net/projects/utalm/
https://github.com/ArnoCan/utalm
WKR
Arno-Can Uestuensoez

Resources