Acho que o problema é que você espera que "$LINENO" forneça a linha de execução do último comando, o que pode funcionar quase, mas clean_a() também obtém seu próprio $LINENO e que você deve fazer em vez disso:
error "something!
line: $1
...
Mas mesmo isso provavelmente não funcionaria porque espero que seja apenas imprimir a linha na qual você definiu o trap .
Aqui está uma pequena demonstração:
PS4='DEBUG: $LINENO : ' \
bash -x <<\CMD
trap 'fn "$LINENO"' EXIT
fn() { printf %s\n "$LINENO" "$1"; }
echo "$LINENO"
CMD
OUTPUT
DEBUG: 1 : trap 'fn "$LINENO"' EXIT
DEBUG: 3 : echo 3
3
DEBUG: 1 : fn 1
DEBUG: 2 : printf '%s\n' 2 1
2
1
Portanto, o trap é definido e, em seguida, fn() é definido e, em seguida, echo é executado. Quando o shell conclui a execução de sua entrada, o EXIT trap é executado e fn é chamado. É passado um argumento - que é o trap da linha $LINENO . fn imprime primeiro seu próprio $LINENO , em seguida, seu primeiro argumento.
Posso pensar em uma maneira de obter o comportamento esperado, mas isso estraga ostderr:
PS4='DEBUG: $((LASTNO=$LINENO)) : ' \
bash -x <<\CMD
trap 'fn "$LINENO" "$LASTNO"' EXIT
fn() { printf %s\n "$LINENO" "$LASTNO" "$@"; }
echo "$LINENO"
CMD
OUTPUT
DEBUG: 1 : trap 'fn "$LINENO" "$LASTNO"' EXIT
DEBUG: 3 : echo 3
3
DEBUG: 1 : fn 1 3
DEBUG: 2 : printf '%s\n' 2 1 1 3
2
1
1
3
Ele usa o prompt de depuração $PS4 do shell para definir $LASTNO em cada linha executada. É uma variável de shell atual que você pode acessar em qualquer lugar dentro do script. Isso significa que não importa qual linha está sendo acessada atualmente, você pode fazer referência à linha mais recente do script executada em $LASTNO . Claro, como você pode ver, vem com saída de depuração. Você pode enviar isso para 2>/dev/null para a maioria da execução do script, e apenas 2>&1 em clean_a() ou algo assim.
O motivo pelo qual você obtém 1 em $LASTNO é porque esse é o último valor para o qual $LASTNO foi definido porque esse foi o último valor $LINENO . Você tem seu trap na função archieve_it() e, portanto, ele recebe seu próprio $LINENO , como é indicado na especificação abaixo. Embora não pareça que bash faz a coisa certa de qualquer maneira, também pode ser porque o trap tem que reexecutar o shell em INT signal e $LINENO é, portanto, redefinido. Estou um pouco confuso sobre isso neste caso - como é bash , aparentemente.
Você não quer avaliar $LASTNO em clean_a() , eu acho. Melhor seria avaliá-lo no trap e passar o valor trap recebe em $LASTNO até clean_a() como argumento. Talvez assim:
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO "$BASH_COMMAND"' \
SIGHUP SIGINT SIGTERM SIGQUIT
while :; do sleep 1; done
} 2>/dev/null
clean_a () { : "$@" ; } 2>&1
Tente isso - ele deve fazer o que você quiser, eu acho. Ah - e note que em PS4=^M o ^M é um retorno literal - como CTRL + V ENTER.
Da especificação de shell POSIX :
Set by the shell to a decimal number representing the current sequential line number (numbered starting with 1) within a script or function before it executes each command. If the user unsets or resets
LINENO, the variable may lose its special meaning for the life of the shell. If the shell is not currently executing a script or function, the value ofLINENOis unspecified. This volume of IEEE Std 1003.1-2001 specifies the effects of the variable only for systems supporting the User Portability Utilities option.