AIX非KSH93环境下加载脚本时LINENO变量异常的解决办法
LINENO Tracking for Sourced Scripts in Non-KSH93 Environments I get it—when debugging ksh scripts (non-KSH93 versions) with export PS4='+Line: ${LINENO}: '; set -vx, sourcing another script breaks the line number tracking completely. The LINENO sticks to the line in the main script where you sourced the subscript, even if you set the same PS4 and debug flags inside the subscript. Let's fix that.
Why This Happens
In non-KSH93 ksh implementations, LINENO is a global shell variable. When you source a script with ., the code runs in your current shell session—so it shares the same LINENO counter as the main script. There's no built-in reset for LINENO when sourcing, hence the stuck line number.
Solution: Custom Line Number Tracking with DEBUG Traps
Since we can't rely on the global LINENO to reset for sourced scripts, we'll create a custom local line number variable and use a DEBUG trap to increment it on each command execution. Here's how to implement it:
Step 1: Update the Main Script
Modify your main script to save the current LINENO before sourcing, then restore it afterward:
export PS4='+Line: ${LINENO}: '; set -vx echo "main" echo "echo 'slave 1'" > /tmp/slave.txt echo "echo 'slave 2'" >> /tmp/slave.txt # Save current line number before sourcing prev_lineno=$LINENO # Source the subscript, passing a starting line number (1 for first line of subscript) . /tmp/slave.txt 1 # Restore the original line number for the main script LINENO=$prev_lineno
Step 2: Rewrite the Subscript
Update /tmp/slave.txt to use a custom line number variable and trap to track execution lines:
# Initialize custom line number from the argument passed (default to 1 if no arg) local _sub_lineno=${1:-1} # Override PS4 to use our custom line number PS4="+Line: ${_sub_lineno}: " # Set a DEBUG trap to increment the line number before each command runs trap '_sub_lineno=$((_sub_lineno + 1))' DEBUG # Your subscript code here echo 'slave 1' echo 'slave 2' # Clean up: remove the trap and custom variable to avoid affecting the main script trap - DEBUG unset _sub_lineno
What This Does
- The
local _sub_linenoensures the custom line number is only visible inside the sourced subscript (won't pollute the main script's namespace). - The
DEBUGtrap triggers before every command in the subscript, incrementing our custom line number each time. - We override
PS4temporarily in the subscript to show the custom line number instead of the globalLINENO. - After the subscript finishes, we clean up the trap and variable so the main script's debugging continues as normal.
Test Output
When you run the main script now, you'll see proper line numbers for both the main script and the sourced subscript:
+Line: 2: echo "main" main +Line: 3: echo "echo 'slave 1'" > /tmp/slave.txt +Line: 4: echo "echo 'slave 2'" >> /tmp/slave.txt +Line: 6: prev_lineno=$LINENO +Line: 7: . /tmp/slave.txt 1 +Line: 1: local _sub_lineno=1 +Line: 2: PS4="+Line: ${_sub_lineno}: " +Line: 3: trap '_sub_lineno=$((_sub_lineno + 1))' DEBUG +Line: 4: echo 'slave 1' slave 1 +Line: 5: echo 'slave 2' slave 2 +Line: 6: trap - DEBUG +Line: 7: unset _sub_lineno +Line: 8: LINENO=$prev_lineno
Notes
- If your subscript sources other scripts, you can repeat this pattern: save the current
_sub_linenoand PS4, source the nested script with a new starting line number, then restore the parent subscript's values. - This method works in most non-KSH93 ksh variants (like ksh88) where
LINENOis global andDEBUGtraps are supported.
内容的提问来源于stack exchange,提问作者NeronLeVelu

