Bash - exit does not exit script (only subshell) [duplicate] - bash

How would you exit out of a function if a condition is true without killing the whole script, just return back to before you called the function.
Example
# Start script
Do scripty stuff here
Ok now lets call FUNCT
FUNCT
Here is A to come back to
function FUNCT {
if [ blah is false ]; then
exit the function and go up to A
else
keep running the function
fi
}

Use:
return [n]
From help return
return: return [n]
Return from a shell function.
Causes a function or sourced script to exit with the return value
specified by N. If N is omitted, the return status is that of the
last command executed within the function or script.
Exit Status:
Returns N, or failure if the shell is not executing a function or script.

Use return operator:
function FUNCT {
if [ blah is false ]; then
return 1 # or return 0, or even you can omit the argument.
else
keep running the function
fi
}

If you want to return from an outer function with an error without exiting you can use this trick:
do-something-complex() {
# Using `return` here would only return from `fail`, not from `do-something-complex`.
# Using `exit` would close the entire shell.
# So we (ab)use a different feature. :)
fail() { : "${__fail_fast:?$1}"; }
nested-func() {
try-this || fail "This didn't work"
try-that || fail "That didn't work"
}
nested-func
}
Trying it out:
$ do-something-complex
try-this: command not found
bash: __fail_fast: This didn't work
This has the added benefit/drawback that you can optionally turn off this feature: __fail_fast=x do-something-complex.
Note that this causes the outermost function to return 1.

My use case is to run the function unless it's already running. I'm doing
mkdir /tmp/nice_exit || return 0
And then at the end of the function
rm -rf /tmp/nice_exit

Related

Error exit code 1 code showing in Jenkins Consiole output ( I do not want to see it )

I have a job running in the Jenkins pipeline and the output is showing error exit code 1 because am using if statement to create NOT_BUILT in the stage. Is there any other way to not see the work error exit code 1. I do not want to use When statement but if possible to still use IF statement and have a blank stage but without this message error exit code 1 in the console output.
This is my script below :
if(route53 == 'false' ) {
catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
sh "exit 1"
}
}
else if(route53 == 'true' && all == "Yes" ) {
catchError(buildResult: 'SUCCESS', stageResult: 'NOT_BUILT') {
sh "exit 1"
}
}
The result in the pipeline console output is showing this, the stage graphic is fine as it is showing a blank stage but the console output error code is what I really want to manipulate.
output result
+ exit 1
[Pipeline] }
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }
ERROR: script returned exit code 1
[Pipeline] }
When using declarative pipelines the NOT_BUILT state is preserved to a stage the was not executed because its when directive was evaluated as false, and there is not direct way to set it except with the catchError workaround. (btw you can control the error message by using error('Your Message') instead of exit 1)
Therefore, it is easiest to achieve using the when directive and also makes your pipeline more readable. If you insist on using if statements you can still use them inside a when directive with the generic expression option which allows you to run any groovy code and calculate the relevant Boolean value according to your needs.
So you can still use your original code and just update it to return a Boolean:
stage('Conditional stage') {
when {
expression {
if(route53 == 'false' ) {
return false
}
else if(route53 == 'true' && all == "Yes" ) {
return false
}
return true
}
}
steps {
...
}
}

Jump to the next function by pressing Ctrl-C

Assume that there are some functions which they do different jobs. I want to be able to press Ctrl-C to jump to the next function instead of canceling all the script at once.
I tried trap ctrl_c INT but it didn't work. FYI, I use curl in some of the functions.
How can I do it?
function first {
# do the first job
}
function second {
# do the second job
}
function third {
# do the third job
}
first &&
second &&
third &&
rm *.del
Hooking Ctrl+C to return 0 seems to work fine. Like:
# define first, second, and third here
trap 'return 0' INT
first &&
second &&
third &&
trap - INT &&
rm *.del

How to exit a promise from within a promise?

How do I exit a promise from within a promise? The perl6 docs do not provide an easy method. For example:
my $x = start {
loop { # loop forever until "quit" is seen
my $y = prompt("Say something: ");
if $y ~~ / quit / {
# I want to exit the promise from here;
# "break" and "this.break" are not defined;
# "return" does not break the promise;
# I do NOT want an error exception when exiting a promise;
# I want to return a value as the result of this promise;
}
else { say $y; }
}
}
I do not want to be in the promise loop forever. break() and this.break() are not recognized, and return does not break the promise.
Use the last keyword to quit the loop.
The kept value of a start block is the value returned by its last statement.
So:
my $x = start {
loop { # loop forever until "quit" is seen
my $y = prompt("Say something: ");
if $y ~~ / quit / {
last
}
else { say $y; }
}
42 # <-- The promise will be kept with value `42`
}

Why return value from a function following local declaration in bash is always 0?

In a script of bash below, I declare a variable followed by a function. And I tried to get the return value of the function. It should be 1 but it was always 0. When I remove the local declaration, it works as I want.
Why local declaration breaks the return value of the following function?
Is local declaration a type of command, like "if []"?
Please let me know the reason.
My test function is following,
function inner_func() {
local RETURN_00=1
echo "RETURN_00 = $RETURN_00"
echo "RETURN_00 = $RETURN_00" >&2
return $RETURN_00
}
function func() {
local ECHO_00=$(inner_func) # this local declaration is a problem
local RETURN_01=$?
echo "RETURN_01 = $RETURN_01"
echo "RETURN_01 = $RETURN_01" >&2
return $RETURN_01
}
ECHO_01=$(func)
RESULT=$?
echo "RESULT = $RESULT"
Results of above code are following
RETURN_00 = 1
RETURN_01 = 0
RESULT = 0
local is a command of its own accord, so using it resets $? to 0 (assuming the local assignment is successful), so when you do:
local ECHO_00=$(inner_func)
local RETURN_01=$? # $? has already been reset to 0 by the command local on the previous line.
Instead you can do this:
local ECHO_00
ECHO_00=$(inner_func)
local RETURN_01=$?
That way ECHO_00 is still local, but you can also access the return value from the function you called in the subshell. Output:
RETURN_00 = 1
RETURN_01 = 1
RESULT = 1
When a local variable is declared and assigned in the same command, the variable assignment takes place before the local declaration. So the value of $? is the return value of the local declaration operation.
See http://tldp.org/LDP/abs/html/localvar.html (3rd grey block from the top)

Recursive Function return value in vb script

Please see below function fnWaitCheckFinalStatus if Else part is executed in below code then value return by Function fnWaitCheckFinalStatus is coming blank because function this is called recursively fnWaitCheckFinalStatus.
Is there way to get return value of fnWaitCheckFinalStatus After exit function function should exit all its state.
How can I make it possible , any pointers on this.
Function fnWaitCheckFinalStatus(objStatusBar)
Dim blnRetValue : blnRetValue = True
Dim i : i=0
If objStatusBar.Exist Then
strValue=ObjStatusBar.GetROProperty("text")
Do
wait 10
strValue=ObjStatusBar.GetROProperty("text")
Loop While strValue = "Task Started"
End If
strValue1=ObjStatusBar.GetROProperty("text")
If strValue1="Task executed successfully" Then
blnRetValue1=True
fnWaitCheckFinalStatus = blnRetValue1
Exit Function
ElseIf strValue1="Task execution failed" Then
blnRetValue1=False
fnWaitCheckFinalStatus = blnRetValue1
Exit Function
Else
Call fnWaitCheckFinalStatus(objStatusBar)
End If
End Function
Consider "pass-through"ing the function result if you return from the recursion, like in this code (note the line with the !!! comment):
Function fnWaitCheckFinalStatus(objStatusBar)
Dim i : i=0
If objStatusBar.Exist Then
strValue=ObjStatusBar.GetROProperty("text")
Do
wait 10
strValue=ObjStatusBar.GetROProperty("text")
Loop While strValue = "Task Started"
End If
strValue1=ObjStatusBar.GetROProperty("text")
If strValue1="Task executed successfully" Then
fnWaitCheckFinalStatus = true
ElseIf strValue1="Task execution failed" Then
fnWaitCheckFinalStatus = false
Else
fnWaitCheckFinalStatus=fnWaitCheckFinalStatus(objStatusBar) ' !!!
End If
End Function
Also, I eliminated the result buffer variable. You donĀ“t need it, so you can scratch it.
Also, I'd avoid exit function in this case to keep the code simpler (one entry point, one exit point), so I eliminated that, too.
Generally speaking, there is no obvious reason for using recursion here since you pass exactly the same argument as you receive, so the recursive call will do exactly the same as its caller scope. Use a loop instead.

Resources