How do I find the line number in Bash when an error occured?
Clash Royale CLAN TAG#URR8PPP
up vote
16
down vote
favorite
How do you find the line number in Bash where an error occurred?
Example
I create the following simple script with line numbers to explain what we need. The script will copy files from
cp $file1 $file2
cp $file3 $file4
When one of the cp
commands fail then the function will exit with exit 1. We want to add the ability to the function to also print the error with the line number (for example, 8 or 12).
Is this possible?
Sample script
1 #!/bin/bash
2
3
4 function in_case_fail
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
linux bash shell-script scripting logs
add a comment |Â
up vote
16
down vote
favorite
How do you find the line number in Bash where an error occurred?
Example
I create the following simple script with line numbers to explain what we need. The script will copy files from
cp $file1 $file2
cp $file3 $file4
When one of the cp
commands fail then the function will exit with exit 1. We want to add the ability to the function to also print the error with the line number (for example, 8 or 12).
Is this possible?
Sample script
1 #!/bin/bash
2
3
4 function in_case_fail
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
linux bash shell-script scripting logs
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
You could useset -x
and/orset -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.
– Rolf
Aug 23 at 8:34
add a comment |Â
up vote
16
down vote
favorite
up vote
16
down vote
favorite
How do you find the line number in Bash where an error occurred?
Example
I create the following simple script with line numbers to explain what we need. The script will copy files from
cp $file1 $file2
cp $file3 $file4
When one of the cp
commands fail then the function will exit with exit 1. We want to add the ability to the function to also print the error with the line number (for example, 8 or 12).
Is this possible?
Sample script
1 #!/bin/bash
2
3
4 function in_case_fail
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
linux bash shell-script scripting logs
How do you find the line number in Bash where an error occurred?
Example
I create the following simple script with line numbers to explain what we need. The script will copy files from
cp $file1 $file2
cp $file3 $file4
When one of the cp
commands fail then the function will exit with exit 1. We want to add the ability to the function to also print the error with the line number (for example, 8 or 12).
Is this possible?
Sample script
1 #!/bin/bash
2
3
4 function in_case_fail
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
linux bash shell-script scripting logs
edited Aug 13 at 1:46
Peter Mortensen
79148
79148
asked Aug 12 at 17:18
yael
2,0301145
2,0301145
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
You could useset -x
and/orset -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.
– Rolf
Aug 23 at 8:34
add a comment |Â
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
You could useset -x
and/orset -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.
– Rolf
Aug 23 at 8:34
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
You could use
set -x
and/or set -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.– Rolf
Aug 23 at 8:34
You could use
set -x
and/or set -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.– Rolf
Aug 23 at 8:34
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
25
down vote
accepted
Rather than use your function, I'd use this method instead:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure()
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
trap 'failure $LINENO "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
This works by trapping on ERR and then calling the failure()
function with the current line number + bash command that was executed.
Example
Here I've not taken any care to create the files, f1
, f2
, f3
, or f4
. When I run the above script:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
It fails, reporting the line number plus command that was executed.
add a comment |Â
up vote
12
down vote
In addition to LINENO
containing the current line number, there are the BASH_LINENO
and FUNCNAME
(and BASH_SOURCE
) arrays that contain the function names and line numbers they're called from.
So you could do something like this:
#!/bin/bash
error()
printf "'%s' failed with exit code %d in function '%s' at line %d.n" "$1-something" "$?" "$FUNCNAME[1]" "$BASH_LINENO[0]"
foo() error "this thing"
( exit 123 )
foo
Running that would print
'that thing' failed with exit code 123 in function 'foo' at line 9.
If you use set -e
, or trap ... ERR
to automatically detect errors, note that they have some caveats. It's also harder to include a description of what the script was doing at the time (as you did in your example), though that might be more useful to a regular user than just the line number.
See e.g. these for the issues with set -e
and others:
- Why does set -e not work inside subshells with parenthesis () followed by an OR list ||?
- bash -e exits when let or expr evaluates to 0
- BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
add a comment |Â
up vote
10
down vote
Bash has a built-in variable $LINENO
which is replaced by the current line number when in a statement, so you can do
in_case_fail $? "at $LINENO: cp $file1 $file2"
You could also try using trap ... ERR
which runs when a command fails (if the result is not tested). Eg:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Then if a command like cp $file1 $file2
fails you will get the error message with the line number and an exit. You will also find the command in error in variable $BASH_COMMAND
(though not any redirections etc.).
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
25
down vote
accepted
Rather than use your function, I'd use this method instead:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure()
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
trap 'failure $LINENO "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
This works by trapping on ERR and then calling the failure()
function with the current line number + bash command that was executed.
Example
Here I've not taken any care to create the files, f1
, f2
, f3
, or f4
. When I run the above script:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
It fails, reporting the line number plus command that was executed.
add a comment |Â
up vote
25
down vote
accepted
Rather than use your function, I'd use this method instead:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure()
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
trap 'failure $LINENO "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
This works by trapping on ERR and then calling the failure()
function with the current line number + bash command that was executed.
Example
Here I've not taken any care to create the files, f1
, f2
, f3
, or f4
. When I run the above script:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
It fails, reporting the line number plus command that was executed.
add a comment |Â
up vote
25
down vote
accepted
up vote
25
down vote
accepted
Rather than use your function, I'd use this method instead:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure()
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
trap 'failure $LINENO "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
This works by trapping on ERR and then calling the failure()
function with the current line number + bash command that was executed.
Example
Here I've not taken any care to create the files, f1
, f2
, f3
, or f4
. When I run the above script:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
It fails, reporting the line number plus command that was executed.
Rather than use your function, I'd use this method instead:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure()
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
trap 'failure $LINENO "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
This works by trapping on ERR and then calling the failure()
function with the current line number + bash command that was executed.
Example
Here I've not taken any care to create the files, f1
, f2
, f3
, or f4
. When I run the above script:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
It fails, reporting the line number plus command that was executed.
edited Aug 19 at 11:50


ilkkachu
50.2k677138
50.2k677138
answered Aug 12 at 17:23
slm♦
237k65484657
237k65484657
add a comment |Â
add a comment |Â
up vote
12
down vote
In addition to LINENO
containing the current line number, there are the BASH_LINENO
and FUNCNAME
(and BASH_SOURCE
) arrays that contain the function names and line numbers they're called from.
So you could do something like this:
#!/bin/bash
error()
printf "'%s' failed with exit code %d in function '%s' at line %d.n" "$1-something" "$?" "$FUNCNAME[1]" "$BASH_LINENO[0]"
foo() error "this thing"
( exit 123 )
foo
Running that would print
'that thing' failed with exit code 123 in function 'foo' at line 9.
If you use set -e
, or trap ... ERR
to automatically detect errors, note that they have some caveats. It's also harder to include a description of what the script was doing at the time (as you did in your example), though that might be more useful to a regular user than just the line number.
See e.g. these for the issues with set -e
and others:
- Why does set -e not work inside subshells with parenthesis () followed by an OR list ||?
- bash -e exits when let or expr evaluates to 0
- BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
add a comment |Â
up vote
12
down vote
In addition to LINENO
containing the current line number, there are the BASH_LINENO
and FUNCNAME
(and BASH_SOURCE
) arrays that contain the function names and line numbers they're called from.
So you could do something like this:
#!/bin/bash
error()
printf "'%s' failed with exit code %d in function '%s' at line %d.n" "$1-something" "$?" "$FUNCNAME[1]" "$BASH_LINENO[0]"
foo() error "this thing"
( exit 123 )
foo
Running that would print
'that thing' failed with exit code 123 in function 'foo' at line 9.
If you use set -e
, or trap ... ERR
to automatically detect errors, note that they have some caveats. It's also harder to include a description of what the script was doing at the time (as you did in your example), though that might be more useful to a regular user than just the line number.
See e.g. these for the issues with set -e
and others:
- Why does set -e not work inside subshells with parenthesis () followed by an OR list ||?
- bash -e exits when let or expr evaluates to 0
- BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
add a comment |Â
up vote
12
down vote
up vote
12
down vote
In addition to LINENO
containing the current line number, there are the BASH_LINENO
and FUNCNAME
(and BASH_SOURCE
) arrays that contain the function names and line numbers they're called from.
So you could do something like this:
#!/bin/bash
error()
printf "'%s' failed with exit code %d in function '%s' at line %d.n" "$1-something" "$?" "$FUNCNAME[1]" "$BASH_LINENO[0]"
foo() error "this thing"
( exit 123 )
foo
Running that would print
'that thing' failed with exit code 123 in function 'foo' at line 9.
If you use set -e
, or trap ... ERR
to automatically detect errors, note that they have some caveats. It's also harder to include a description of what the script was doing at the time (as you did in your example), though that might be more useful to a regular user than just the line number.
See e.g. these for the issues with set -e
and others:
- Why does set -e not work inside subshells with parenthesis () followed by an OR list ||?
- bash -e exits when let or expr evaluates to 0
- BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
In addition to LINENO
containing the current line number, there are the BASH_LINENO
and FUNCNAME
(and BASH_SOURCE
) arrays that contain the function names and line numbers they're called from.
So you could do something like this:
#!/bin/bash
error()
printf "'%s' failed with exit code %d in function '%s' at line %d.n" "$1-something" "$?" "$FUNCNAME[1]" "$BASH_LINENO[0]"
foo() error "this thing"
( exit 123 )
foo
Running that would print
'that thing' failed with exit code 123 in function 'foo' at line 9.
If you use set -e
, or trap ... ERR
to automatically detect errors, note that they have some caveats. It's also harder to include a description of what the script was doing at the time (as you did in your example), though that might be more useful to a regular user than just the line number.
See e.g. these for the issues with set -e
and others:
- Why does set -e not work inside subshells with parenthesis () followed by an OR list ||?
- bash -e exits when let or expr evaluates to 0
- BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
edited Aug 12 at 19:12
answered Aug 12 at 19:00


ilkkachu
50.2k677138
50.2k677138
add a comment |Â
add a comment |Â
up vote
10
down vote
Bash has a built-in variable $LINENO
which is replaced by the current line number when in a statement, so you can do
in_case_fail $? "at $LINENO: cp $file1 $file2"
You could also try using trap ... ERR
which runs when a command fails (if the result is not tested). Eg:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Then if a command like cp $file1 $file2
fails you will get the error message with the line number and an exit. You will also find the command in error in variable $BASH_COMMAND
(though not any redirections etc.).
add a comment |Â
up vote
10
down vote
Bash has a built-in variable $LINENO
which is replaced by the current line number when in a statement, so you can do
in_case_fail $? "at $LINENO: cp $file1 $file2"
You could also try using trap ... ERR
which runs when a command fails (if the result is not tested). Eg:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Then if a command like cp $file1 $file2
fails you will get the error message with the line number and an exit. You will also find the command in error in variable $BASH_COMMAND
(though not any redirections etc.).
add a comment |Â
up vote
10
down vote
up vote
10
down vote
Bash has a built-in variable $LINENO
which is replaced by the current line number when in a statement, so you can do
in_case_fail $? "at $LINENO: cp $file1 $file2"
You could also try using trap ... ERR
which runs when a command fails (if the result is not tested). Eg:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Then if a command like cp $file1 $file2
fails you will get the error message with the line number and an exit. You will also find the command in error in variable $BASH_COMMAND
(though not any redirections etc.).
Bash has a built-in variable $LINENO
which is replaced by the current line number when in a statement, so you can do
in_case_fail $? "at $LINENO: cp $file1 $file2"
You could also try using trap ... ERR
which runs when a command fails (if the result is not tested). Eg:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Then if a command like cp $file1 $file2
fails you will get the error message with the line number and an exit. You will also find the command in error in variable $BASH_COMMAND
(though not any redirections etc.).
edited Aug 12 at 18:34
answered Aug 12 at 18:22


meuh
29.5k11750
29.5k11750
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f462156%2fhow-do-i-find-the-line-number-in-bash-when-an-error-occured%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Related - stackoverflow.com/questions/24398691/…
– slm♦
Aug 12 at 18:26
You could use
set -x
and/orset -v
to trace what has been executed. Not exactly what you asked for but it will probably be helpful, too.– Rolf
Aug 23 at 8:34