问题
In shell script, echo can be used to return values from functions. But, if those functions want to print some messages. Then, this can be done by redirecting it to error stream. Below is a simplified example :-
#this is a function that returns a value, as well as
#print some messages
function logic(){
echo >&2 "start of logic"
echo >&2 "perform logic, to get value"
echo "ok"
}
function smain(){
local result=$(logic)
echo "result is >$result<"
if [ "$result" == "ok" ];then
echo "script successful"
else
echo "script failed"
fi
}
smain
Below is the sample execution output :-
sh sample.sh
start of logic
perform logic, to get value
result is >ok<
script successful
That works fine. But when this script is used as a autosys job. then messages from logic functions ends up in error stream file triggering alerts.
Is there any way, messages from logic function can be written to output stream and not mixing messages with return value.
Edit 1 :-
#!/usr/bin/env bash
function Return(){
printf -v "$1" '%s' '$*'
}
function logic() {
local arg=$1
local system=$2
echo "start of logic"
echo "all params are >$*<"
echo "perform logic, to get value"
echo >&2 "logic successfully completed"
printf -v "$1" '%s' 'abraKaDabra'
}
function main() {
local result='' ; logic "$@" result
printf 'result is >%s<\n' "$result"
if [ "$result" = "ok" ]; then
echo "script successful"
else
echo "script failed"
fi
echo >&2 "end of main"
}
main "$@"
Output :-
$
sh returnValueWithDebugging.sh abc xyz > out.log 2>err.log
$
cat err.log
logic successfully completed
end of main
$
cat out.log
start of logic
all params are >abc xyz result<
perform logic, to get value
result is ><
script failed
回答1:
Would this work?:
#this is a function that returns a value, as well as
#print some messages
function logic(){
echo "start of logic"
echo "perform logic, to get value"
echo "ok" >&2
}
function smain(){
{ local result=$( { { logic ; } 1>&3 ; } 2>&1); } 3>&1
echo "result is >$result<"
if [ "$result" == "ok" ];then
echo "script successful"
else
echo "script failed"
fi
}
smain
回答2:
I'd suggest you use the return code if the return of the function is a simple state indicator (like ok or fail).
And since you tag your question as Bash, returning arbitrary values can be achieved by reference rather than using an output stream, with the advantage of not calling your function within sub-shell processes:
Passing return value as reference (result variable name passed as argument 1):
#!/usr/bin/env bash
logic()
{
echo "start of logic"
echo "perform logic, to get value"
printf -v "$1" '%s' 'ok'
}
function main ()
{
result=''
logic result
printf 'result is >%s<\n' "$result"
if [ "$result" = "ok" ];then
echo "script successful"
else
echo "script failed"
fi
}
main "$@"
Alternatively you can use name-ref variables with declare -n
and write the logic
function as:
logic()
{
local -n res="$1"
echo "start of logic"
echo "perform logic, to get value"
res='ok'
}
Another example with additional parameters used by logic
:
#!/usr/bin/env bash
logic()
{
local -n res="$1"
local a="$2"
local b="$3"
echo "start of logic"
echo "perform logic, to get value"
if [ $a -gt $b ]; then
res='ok'
else
res='oh no!'
fi
}
function main ()
{
result=''
logic result 3 2
printf 'result is >%s<\n' "$result"
if [ "$result" = "ok" ];then
echo "script successful"
else
echo "script failed"
fi
logic result 5 10
printf 'result is >%s<\n' "$result"
}
main "$@"
来源:https://stackoverflow.com/questions/62738633/write-to-output-stream-and-returning-value-from-shell-script-function