I want to create a message for terminal errors.
But my code does not work! :(
local return_code=""
local code="%?"
if [ "$code" = "130" ]; then
return_code="%F{red}TERMINATED BY USER ↵%f"
elif [ "$code" = "0" ]; then
return_code=""
else
return_code="%F{red}${code} ↵%f" # <= always return
fi
Or I used another method
local code=$? # always return zero
if [ $code -eq 130 ]; then
...
I found the answer in the comments and thank you
local e001="%(1?.(!) GENERAL ERROR%f ↵."
local e002="%(2?.(!) MISUSE OF SHELL BUILTINS%f ↵."
local e126="%(126?.(!) COMMAND INVOKED CANNOT EXECUTE%f ↵."
local e127="%(127?.(!) COMMAND NOT FOUND%f ↵."
local e128="%(128?.(!) INVALID ARGUMENT TO EXIT%f ↵."
local e130="%(130?.(!) TERMINATED BY USER%f ↵."
local e255="%(255?.(!) EXIT STATUS OUT OF RANGE%f ↵."
local return_code="%F{red}${e001}${e002}${e126}${e127}${e128}${e130}${e255}%(?..%?%f ↵)"
There was no need for conditions
Related
when I am running a Tcl script that contains the following lines:
set V [exec bjobs ]
puts "bjobs= ${V}"
When jobs are present it's working properly but, no jobs are running it is showing an error like this:
No unfinished job found
while executing
"exec bjobs "
invoked from within
"set V [exec bjobs ]"
How to avoid this error? Please let me know how to avoid this kind of errors.
It sounds to me like the bjobs program has a non-zero exit code in this case. The exec manual page includes this example in a subsection WORKING WITH NON-ZERO RESULTS:
To execute a program that can return a non-zero result, you should wrap
the call to exec in catch and check the contents of the -errorcode
return option if you have an error:
set status 0
if {[catch {exec grep foo bar.txt} results options]} {
set details [dict get $options -errorcode]
if {[lindex $details 0] eq "CHILDSTATUS"} {
set status [lindex $details 2]
} else {
# Some other error; regenerate it to let caller handle
return -options $options -level 0 $results
}
}
This is more easily written using the try command, as that makes it
simpler to trap specific types of errors. This is done using code like
this:
try {
set results [exec grep foo bar.txt]
set status 0
} trap CHILDSTATUS {results options} {
set status [lindex [dict get $options -errorcode] 2]
}
I think you could write this as:
try {
set V [exec bjobs ]
} trap CHILDSTATUS {message} {
# Not sure how you want to handle the case where there's nothing...
set V $message
}
puts "bjobs= ${V}"
if {[catch {exec bjobs} result]} {
puts "bjobs have some issues. Reason : $result"
} else {
puts "bjobs executed successfully. Result : $result"
}
Reference : catch
Note carefully in the exec man
page:
If any of the commands in the pipeline exit abnormally or are killed or
suspended, then exec will return an error [...]
If any of the commands
writes to its standard error file and that standard error is not
redirected and
-ignorestderr is not specified, then exec will return an
error.
So if bjobs returns non-zero or prints to stderr when there are no jobs, exec needs catch or try as Donal writes.
I'm trying to customise the deploy scripts to allow me to deploy each of my four API proxies from the command line. It looks very similar to the one provided in the samples on Github:
#!/bin/bash
if [[ $# -eq 0 ]] ; then
echo 'Must provide proxy name.'
exit 0
fi
dirname=$1
proxyname="teamname-"$dirname
source ./setup/setenv.sh
echo "Enter your password for user $username in the Apigee Enterprise organization $org, followed by [ENTER]:"
read -s password
echo Deploying $proxyname to $env on $url using $username and $org
./tools/deploy.py -n $proxyname -u $username:$password -o $org -h $url -e $env -p / -d ./$dirname
echo "If 'State: deployed', then your API Proxy is ready to be invoked."
echo "Run '$ sh invoke.sh'"
echo "If you get errors, make sure you have set the proper account settings in /setup/setenv.sh"
However when I run it, I get the following response:
Deploying teamname-gameassets to int on https://api.enterprise.apigee.com using my-email-address and org-name
Writing ./gameassets/teamname-gameassets.xml to ./teamname-gameassets.xml
Writing ./gameassets/policies/Add-CORS.xml to policies/Add-CORS.xml
Writing ./gameassets/proxies/default.xml to proxies/default.xml
Writing ./gameassets/targets/development.xml to targets/development.xml
Writing ./gameassets/targets/production.xml to targets/production.xml
Import failed to /v1/organizations/org-name/apis?action=import&name=teamname-gameassets with status 500:
{
"code" : "messaging.config.beans.ImportFailed",
"message" : "Failed to import the bundle : java.lang.NullPointerException",
"contexts" : [ ],
"cause" : {
"contexts" : [ ]
}
}
How should I go about debugging when I receive errors during the deploy process? Is there some sort of console I can view once logged in to Apigee?
I'm not sure how your proxy ended up this way, but it looks like the top-level directory is named "gameassets." It should be named "apiproxy". If you rename this directory you should see a successful deployment.
Also, before you customize too much, please try out "apigeetool," which is a more flexible command-line tool for deploying proxies:
https://github.com/apigee/api-platform-tools
I have an init.d script to start my process on boot and requires networking to be initialized. I can use utility nm-online which comes with NetworkManager package but problem will be at deployment where NW will be not installed so I have to have some other reliable option which can tell me network is set and I can connect to other server over network. I can keep trying till I get the networking up or connection is set but that will cause some other problem related to error reporting.
Here is the similar question asked for some other folk.
How to detect when networking initialized in /etc/init.d script?
wait_for_network()
{
[ -z "${LINKDELAY}" ] && LINKDELAY=10
$INFO "Waiting for network..."
if [ -f /usr/sbin/nm-online ]; then
nm-online -q --timeout=$LINKDELAY || nm-online -q -x --timeout=30
else
check_for_network_up $LINKDELAY || check_for_network_up 30
fi
[ "$?" = "0" ] && success "network startup" || failure "network startup"
echo
}
I was trying some other approach where I can check for route table. If network is not up, route command return zero entry but problem is I don’t know real number of route entry. It could be two on one machine where 10 on other machine.
check_for_network_up_old3() {
let no_of_routes=`/bin/netstat -rn | wc -l`
$INFO "netstat result $?"
timeout=$1
while [ "$timeout" != "0" ]; do
let routes=`/sbin/ip route show | wc -l`
$INFO "$routes"
if [ $routes -gt 1 ]; then
return 0
fi
timeout=$((timeout-1))
sleep 1
$INFO "check_for_network_up $timeout"
done
return 1
}
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.
I want to be able to tell if a command exists on any POSIX system from a shell script.
On Linux, I can do the following:
if which <command>; then
...snip...
fi
However, Solaris and MacOS which do not give an exit failure code when the command does not exist, they just print an error message to STDOUT.
Also, I recently discovered that the which command itself is not POSIX (see http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html)
Any ideas?
command -v is a POSIX specified command that does what which does.
It is defined to to return >0 when the command is not found or an error occurs.
You could read the stdout/stderr of "which" into a variable or an array (using backticks) rather than checking for an exit code.
If the system does not have a "which" or "where" command, you could also grab the contents of the $PATH variable, then loop over all the directories and search for the given executable. That's essentially what which does (although it might use some caching/optimization of $PATH results).
One which utility is available as shell script in the Git repository of debianutils package of Debian Linux. The script seems to be POSIX compatible and you could use it, if you take into account copyright and license. Note that there have been some controversy whether or not and how the which utility should be deprecated; (at time of writing) current version in Git shows deprecation message whereas an earlier version added later removed -s option to enable silent operation.
command -v as such is problematic as it may output a shell function name, an alias definition, a keyword, a builtin or a non-executable file path. On the other hand some path(s) output by which would not be executed by shell if you run the respective argument as such or as an argument for command. As an alternative for using the which script, a POSIX shell function using command -v could be something like
#!/bin/sh
# Argument $1 should be the basename of the command to be searched for.
# Outputs the absolute path of the command with that name found first in
# a directory listed in PATH environment variable, if the name is not
# shadowed by a special built-in utility, a regular built-in utility not
# associated with a PATH search, or a shell reserved word; otherwise
# outputs nothing and returns 1. If this function prints something for
# an argument, it is the path of the same executable as what 'command'
# would execute for the same argument.
executable() {
if cmd=$(unset -f -- "$1"; command -v -- "$1") \
&& [ -z "${cmd##/*}" ] && [ -x "$cmd" ]; then
printf '%s\n' "$cmd"
else
return 1
fi
}
Disclaimer: Note that the script using command -v above does not find an executable whose name equals a name of a special built-in utility, a regular built-in utility not associated with a PATH search, or a shell reserved word. It might not find an executable either in case if there is non-executable file and executable file available in PATH search.
A function_command_exists for checking if a command exists:
#!/bin/sh
set -eu
function_command_exists() {
local command="$1"
local IFS=":" # paths are delimited with a colon in $PATH
# iterate over dir paths having executables
for search_dir in $PATH
do
# seek only in dir (excluding subdirs) for a file with an exact (case sensitive) name
found_path="$(find "$search_dir" -maxdepth 1 -name "$command" -type f 2>/dev/null)"
# (positive) if a path to a command was found and it was executable
test -n "$found_path" && \
test -x "$found_path" && \
return 0
done
# (negative) if a path to an executable of a command was not found
return 1
}
# example usage
echo "example 1";
command="ls"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
command="notpresent"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
echo "example 2";
command="ls"
function_command_exists "$command" && echo "Command: "\'$command\'" exists"
command="notpresent"
function_command_exists "$command" && echo "Command: "\'$command\'" does not exist"
echo "End of the script"
output:
example 1
Command: 'ls' exists
Command: 'notpresent' does not exist
example 2
Command: 'ls' exists
End of the script
Note that even the set -eu that turns -e option for the script was used the script was executed to the last line "End of the script"
There is no Command: 'notpresent' does not exist in the example 2 because of the && operator so the execution of echo "Command: "\'$command\'" does not exist" is skipped but the execution of the script continues till the end.
Note that the function_command_exists does not check if you have a right to execute the command. This needs to be done separately.
Solution with command -v <command-to-check>
#!/bin/sh
set -eu;
# check if a command exists (Yes)
command -v echo > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 1>"
fi
# check if a command exists (No)
command -v command-that-does-not-exists > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
produces:
<handle not found 2>
because echo was found at the first example.
Solution with running a command and handling errors including command not found.
#!/bin/sh
set -eu;
# check if a command exists (No)
command -v command-that-does-not-exist > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
# run command and handle errors (no problem expected, echo exist)
echo "three" && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 3>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 3>"
fi
# run command and handle errors (<handle not found 4> expected)
command-that-does-not-exist && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 4>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 4>"
fi
# run command and handle errors (command exists but <handle other error 5> expected)
ls non-existing-path && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 5>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 5>"
fi
produces:
<handle not found 2>
three
./function_command_exists.sh: 34: ./function_command_exists.sh: command-that-does-not-exist: not found
<handle not found 4>
ls: cannot access 'non-existing-path': No such file or directory
<handle other error 5>
The following works in both bash and zsh and avoids both functions and aliases.
It returns 1 if the binary is not found.
bin_path () {
if [[ -n ${ZSH_VERSION:-} ]]; then
builtin whence -cp "$1" 2> /dev/null
else
builtin type -P "$1"
fi
}