Issue using If statments in Unix - unix

I'm new to shell scripting and need some help. I am trying to write a script to bounce some servers and I am having a few issues with my if statements. The First and Second one below is giving me a too many arguments error.
For the first one, I am the variable $jmsProcess is a ps -ef | grep command and I only want to go into the if-statement, if this returns some results. This is the same issue for the second one.
In the Third if-statement I want it to check if either of those variables have the value true but this gives me a
if[ [ false || false ] == true ]: command not found
Error.
#Check the JMS process has been killed
if [ $jmsProcess != null ] # SHOULD THIS BE NULL???
then
echo "JMS Process is still running"
$jmsRunning = "true"
fi
#Check the Bone process has been killed
if [ $boneProcess != null ] # SHOULD THIS BE NULL???
then
echo "B-One Process is still Running"
$boneRunning = "true"
fi
if[ [ $jmsRunning || $boneRunning ] == true ] # CHECK THIS FOR QUOTES
then
# $killProcess
fi

null is not a Bash keyword. If you want to check whether a variable is defined, you can do the following:
if [ "${var+defined}" = defined ]
To check whether it's empty or undefined:
if [ -z "${var-}" ]

We don't know how you're setting any of the variable values, (jmsProcess, boneProcess).
Try surrounding all var values like "$var" (with dbl-quotes) and see if the error messages change.
Also there are numerous syntax issues in code visible above. Hard to tell if it is an artifact of posting here, (The code block feature is pretty robust), so I'm going to comment on what I see wrong.
if[ [ false || false ] == true ]: command not found
There are a lot of issues here: false is an shell command. Try typing it on the command line and then do echo $?. you should see 1. true; echo $? will return 0. But the if statements continue or fall-over to the else block based on the last return code (with some special case exceptions).
Also, I'm guessing you're trying to make some sort of reg exp with [ false || false ] == true. Won't work. see below.
You can set status variables to have the value of false (or true) which will be evaluated correctly by the shell.
Also, if[ will give the 'command not found' msg. So by using vars that have the value false, you can do
Try
jmsRunning=false ; boneRunning=true
if [[ ${jmsRunning} || ${boneRunning} ]] ; then
echo both NOT running
else
echo at least 1 is running
fi
Change both to false to see the message change.
Also, null is just a string in a shell script, you probably mean "".
Finally, var assignments cannot have spaces surrounding the '=' sign AND do not use the '$' char at the front when it is on the left hand side of the statment, i.e.
boneRunning=true
I hope this helps.

Related

Zsh prompt showing last error code only once

I would like my prompt to show a cross (✘) when the previous command fails. I use the following code:
export PROMPT=$'%(?..✘\n)\n› '
This gives me the following output:
› echo Hello
Hello
› asjdfiasdf
zsh: command not found: asjdfiasdf
✘
›
✘
I would like to modify the prompt so that it does not repeat the cross when the prompt is redrawn after Enter (the third case in the example above).
Is it possible?
I think I got it. Let me know if you find a bug...
preexec() {
preexec_called=1
}
precmd() {
if [ "$?" != 0 ] && [ "$preexec_called" = 1 ]
then echo ✘; unset preexec_called; fi
}
PROMPT=$'\n› '
Result:
› ofaoisfsaoifoisafas
zsh: command not found: ofaoisfsaoifoisafas
✘
›
› echo $? # (not overwritten)
127
I do this in my zsh, though with colors rather than unicode characters. It's the same principle.
First, I set up my colors, ensuring that they are only used when they are supported:
case $TERM in
( rxvt* | vt100* | xterm* | linux | dtterm* | screen )
function PSC() { echo -n "%{\e[${*}m%}"; } # insert color-specifying chars
ERR="%(0?,`PSC '0;32'`,`PSC '1;31'`)" # if last cmd!=err, hash=green, else red
;;
( * )
function PSC() { true; } # no color support? no problem!
ERR=
;;
esac
Next, I set up a magic enter function (thanks to this post about an empty command (ignore the question, see how I adapt it here):
function magic-enter() { # from https://superuser.com/a/625663
if [[ -n $BUFFER ]]
then unset Z_EMPTY_CMD # Enter was pressed on an empty line
else Z_EMPTY_CMD=1 # The line was NOT empty when Enter was pressed
fi
zle accept-line # still perform the standard binding for Enter
}
zle -N magic-enter # define magic-enter as a widget
bindkey "^M" magic-enter # Backup: use ^J
Now it's time to interpret capture the command and use its return code to set the prompt color:
setopt prompt_subst # allow variable substitution
function preexec() { # just after cmd has been read, right before execution
Z_LAST_CMD="$1" # since $_ is unreliable in the prompt
#Z_LAST_CMD="${1[(wr)^(*=*|sudo|-*)]}" # avoid sudo prefix & options
Z_LAST_CMD_START="$(print -Pn '%D{%s.%.}')"
Z_LAST_CMD_START="${Z_LAST_CMD_START%.}" # zsh <= 5.1.1 makes %. a literal dot
Z_LAST_CMD_START="${Z_LAST_CMD_START%[%]}" # zsh <= 4.3.11 makes %. literal
}
function precmd() { # just before the prompt is rendered
local Z_LAST_RETVAL=$? # $? only works on the first line here
Z_PROMPT_EPOCH="$(print -Pn '%D{%s.%.}')" # nanoseconds, like date +%s.%N
Z_PROMPT_EPOCH="${Z_PROMPT_EPOCH%.}" # zsh <= 5.1.1 makes %. a literal dot
Z_PROMPT_EPOCH="${Z_PROMPT_EPOCH%[%]}" # zsh <= 4.3.11 makes %. a literal %.
if [ -n "$Z_LAST_CMD_START" ]; then
Z_LAST_CMD_ELAPSED="$(( $Z_PROMPT_EPOCH - $Z_LAST_CMD_START ))"
Z_LAST_CMD_ELAPSED="$(printf %.3f "$Z_LAST_CMD_ELAPSED")s"
else
Z_LAST_CMD_ELAPSED="unknown time"
fi
# full line for error if we JUST got one (not after hitting <enter>)
if [ -z "$Z_EMPTY_CMD" ] && [ $Z_LAST_RETVAL != 0 ]; then
N=$'\n' # set $N to a literal line break
LERR="$N$(PSC '1;0')[$(PSC '1;31')%D{%Y/%m/%d %T}$(PSC '1;0')]"
LERR="$LERR$(PSC '0;0') code $(PSC '1;31')$Z_LAST_RETVAL"
LERR="$LERR$(PSC '0;0') returned by last command"
LERR="$LERR (run in \$Z_LAST_CMD_ELAPSED):$N"
LERR="$LERR$(PSC '1;31')\$Z_LAST_CMD$(PSC '0;0')$N$N"
print -PR "$LERR"
fi
}
Finally, set the prompt:
PROMPT="$(PSC '0;33')[$(PSC '0;32')%n#%m$(PSC '0;33') %~$PR]$ERR%#$(PSC '0;0') "
Here's how it looks:
A more direct answer to the question, adapted from the above:
function magic-enter() { # from https://superuser.com/a/625663
if [[ -n $BUFFER ]]
then unset Z_EMPTY_CMD # Enter was pressed on an empty line
else Z_EMPTY_CMD=1 # The line was NOT empty when Enter was pressed
fi
zle accept-line # still perform the standard binding for Enter
}
zle -N magic-enter # define magic-enter as a widget
bindkey "^M" magic-enter # Backup: use ^J
function precmd() { # just before the prompt is rendered
local Z_LAST_RETVAL=$? # $? only works on the first line here
# full line for error if we JUST got one (not after hitting <enter>)
if [ -z "$Z_EMPTY_CMD" ] && [ $Z_LAST_RETVAL != 0 ]; then
echo '✘'
fi
}
PROMPT=$'\n› '
With screen shot:
Use the prexec and precmd hooks:
The preexec hook is called before any command executes. It isn't called when no command is executed. For example, if you press enter at an empty prompt, or a prompt that is only whitespace, it won't be called. A call to this hook signals that a command has been run.
The precmd hook is called before the prompt will be displayed to collect the next command. Before printing the prompt you can print out the exit status. In here we can check if a command was just executed, and if there's a status code we want to display.
This is very similar to the solution suggested by #sneep, which is also a great solution. It's worth using the hooks though so that if you've got anything else registering for these hooks they can do so too.
# print exit code once after last command output
function track-exec-command() {
zsh_exec_command=1
}
function print-exit-code() {
local -i code=$?
(( code == 0 )) && return
(( zsh_exec_command != 1 )) && return
unset zsh_exec_command
print -rC1 -- ''${(%):-"%F{160}✘ exit status $code%f"}''
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec track-exec-command
add-zsh-hook precmd print-exit-code
Thanks to everyone for their answers. Four years later, I would like to illustrate a variation on sneep's answer for those looking for the error code and an alert without a symbol. This is a minimalist prompt but when an error occurs it displays the error code and > in red following the top level directory.
preexec() {
preexec_called=1
}
precmd() {
if [ "$?" != 0 ] && [ "$preexec_called" = 1 ]; then
unset preexec_called
PROMPT='%B%F{blue}%1~%f%b%F{red} $? > %F{black}'
else
PROMPT='%B%F{blue}%1~%f%b%F{blue} > %F{black}'
fi
}

Unable to use -C of grep in Unix Shell Script

I am able to use grep in normal command line.
grep "ABC" Filename -C4
This is giving me the desired output which is 4 lines above and below the matched pattern line.
But if I use the same command in a Unix shell script, I am unable to grep the lines above and below the pattern. It is giving me output as the only lines where pattern is matched and an error in the end that cannot says cannot open grep : -C4
The results are similar if I use -A4 and -B4
I'll assume you need a portable POSIX solution without the GNU extensions (-C NUM, -A NUM, and -B NUM are all GNU, as are arguments following the pattern and/or file name).
POSIX grep can't do this, but POSIX awk can. This can be invoked as e.g. grepC -C4 "ABC" Filename (assuming it is named "grepC", is executable, and is in your $PATH):
#!/bin/sh
die() { echo "$*\nUsage: $0 [-C NUMBER] PATTERN [FILE]..." >&2; exit 2; }
CONTEXT=0 # default value
case $1 in
-C ) CONTEXT="$2"; shift 2 ;; # extract "4" from "-C 4"
-C* ) CONTEXT="${1#-C}"; shift ;; # extract "4" from "-C4"
--|-) shift ;; # no args or use std input (implicit)
-* ) [ -f "$1" ] || die "Illegal option '$1'" ;; # non-option non-file
esac
[ "$CONTEXT" -ge 0 ] 2>/dev/null || die "Invalid context '$CONTEXT'"
[ "$#" = 0 ] && die "Missing PATTERN"
PATTERN="$1"
shift
awk '
/'"$PATTERN"'/ {
match='$CONTEXT'
for(i=1; i<=CONTEXT; i++) if(NR>i) print last[i];
print
next
}
match { print; match-- }
{ for(i='$CONTEXT'; i>1; i--) last[i] = last[i-1]; last[1] = $0 }
' "$#"
This sets up die as a fatal error function, then finds the desired lines of context from your arguments (either -C NUMBER or -CNUMBER), with an error for unsupported options (unless they're files).
If the context is not a number or there is no pattern, we again fatally error out.
Otherwise, we save the pattern, shift it away, and reserve the rest of the options for handing to awk as files ("$#").
There are three stanzas in this awk call:
Match the pattern itself. This requires ending the single-quote portion of the string in order to incorporate the $PATTERN variable (which may not behave correctly if imported via awk -v). Upon that match, we store the number of lines of context into the match variable, loop through the previous lines saved in the last hash (if we've gone far enough to have had them), and print them. We then skip to the next line without evaluating the other two stanzas.
If there was a match, we need the next few lines for context. As this stanza prints them, it decrements the counter. A new match (previous stanza) will reset that count.
We need to save previous lines for recalling upon a match. This loops through the number of lines of context we care about and stores them in the last hash. The current line ($0) is stored in last[1].

Unix Scripting if statement correction

im trying to check if my script ran correctly if not, to echo a message, however when i use this if statement, it produces an error on line '9' (if [ $? -eq 0 ]) Saying that a ' is missing.
#!/bin/bash
name=$1
if ["$name" = ""]
then
echo -n "Enter a name to search for: "
read name
fi
if [ $? -eq 0 ]
then
echo "Incorrect Input"
fi
if ["$name" = ""]
is wrong because you must have a space between the [ and the expression (and before the ] as well).
There's nothing obviously wrong with the syntax of
if [ $? -eq 0 ]
but it's always dubious to check exit codes with arithmetic, since that's what if does directly. If your script is as you show it above, the second if statement should always be true. The fact that the previous if statement's expression was false doesn't matter, because the if statement yields zero if no condition tested true. For example:
$ if false; then echo hi; fi; echo $?
0

unix commands in Informatica command task - what am I missing?

I tried a simple
if [ 1 == 1 ]; then echo "Hi"; fi >>/projects/ods/Chk.txt
included in the command task but it fails with error code 512....
what am I missing here?
An if/fi block cannot redirect output.
use
if [ 1 == 1 ]; then echo "Hi">>/projects/ods/Chk.txt; fi
As you indicate this is a simple test case, if you need output from a larger block of if/the/else/fi or other logic, you can wrap it all in a process group and redirect that output..
{
if [ 1 == 1 ]; then
echo "Hi"
else
echo "nope"
fi
} >>/projects/ods/Chk.txt
Also, it's likely that using == is a problem. Typically you'd use 1 -eq 1 or other constructs like if true ; then, or if you really want good math comparisons, use if (( 1 == 1 )) ; then ..., but older shells may or may not support the (( ... )) test.
IHTH
Found this while searching for some my queries.
you should use create mode instead of append mode. >> does not work, same happened with me. try this , if u are still facing this and needed an answer. :)

Validating Variables in Shell Script

What is the best way to make sure that all the environment variables I need for my script have been set?
Currently, I have multiple if-statements which is not very neat:
if [ -z "$VAR1" ]
then
echo VAR1 not set
exit
fi
if [ -z "$VAR2" ]
then
echo VAR2 not set
exit
fi
if [ -z "$VAR3" ]
then
echo VAR3 not set
exit
fi
Is there a better way?
You can use indirection:
vars="FOO BAR"
for var in $vars
do
[[ -z ${!var} ]] &&
echo "Variable ${var} is empty" ||
echo "The value of variable ${var} is ${!var}"
done
Use a for loop in (set of variables u want). Won't that work?
I have this function in my shell library:
# Check that a list of variables are set to non-null values.
# $#: list of names of environment variables. These cannot be variables local
# to the calling function, because this function cannot see them.
# Returns true if all the variables are non-null, false if any are null or unset
varsSet()
{
local var
for var ; do
eval "[ -n \"\$$var\" ] || return 1"
done
}
I use it in code like this:
varsSet VAR1 VAR2 VAR3 || <error handling here>
you can short them a lot:
[ -z "$FOO" ] && echo "FOO is empty"
[ -z "$BAR" ] && echo "BAR is empty"
a better way:
${FOO:?"FOO is null or not set"}
${BAR:?"BAR is null or not set"}
Of course if the number of variables you are going to test is not low, looping as suggested #Aviator maybe useful to avoid repeating code.
Upon #Aviator answer, I'd like to suggest to define a well commented variable containing a list of your variables-to-be-tested. This way you don't make your code cryptic.
TEST_FOR_IS_SET="FOO BAR BAZ"

Resources