เป็นไปได้หรือไม่ที่จะปรับแต่งแอตทริบิวต์ข้อความแสดงข้อผิดพลาดของ Bash
ตัวอย่างเช่นเป็นไปได้ที่จะแก้ไข .bash_profile
เพื่อรับข้อความแสดงข้อผิดพลาด Bash ต่อไปนี้
-bash: cd: foo: No such file or directory
ในสีแดง?
เป็นไปได้หรือไม่ที่จะปรับแต่งแอตทริบิวต์ข้อความแสดงข้อผิดพลาดของ Bash
ตัวอย่างเช่นเป็นไปได้ที่จะแก้ไข .bash_profile
เพื่อรับข้อความแสดงข้อผิดพลาด Bash ต่อไปนี้
-bash: cd: foo: No such file or directory
ในสีแดง?
คำตอบ:
น่าเศร้าที่ไม่มี PS
ตัวแปรพรอมต์เพื่อควบคุมวิธีการนำเสนอข้อผิดพลาด bash
stderred เป็นโซลูชั่นที่ครอบคลุมสำหรับปัญหาประเภทนี้ แต่มัน จะไม่ทำงานหากไม่มีการแก้ไขเนื่องจากมีการยกเว้นฮาร์ดโค้ด สำหรับ bash
(อ่านต่อเพื่อเหตุผลที่ดีว่าทำไม) นอกจากนี้ยังค่อนข้างรบกวน (การฉีด DLL)
hilite คุณต้องใช้มันเป็น wrapper ซึ่งจะไม่สามารถใช้ได้กับคำสั่ง bash builtin cd
.
คำถามของคุณถามเฉพาะเกี่ยวกับข้อความผิดพลาดทุบตีเหล่านี้จะถูกส่งไป stderr
แต่ stderr
ยังแชร์กับกระบวนการลูกใด ๆ เช่นคำสั่งอื่น ๆ ฉันไม่แน่ใจว่าคุณต้องการแยกแยะทั้งสองหรือไม่
ปัญหาที่ซ่อนอยู่ที่นี่ก็คือ bash
ตัวเองเขียนพรอมต์และอินพุตของคุณ (echo) ไปที่ stderr
. เพื่อพิสูจน์:
bash # start a sacrificial shell
exec 2> tmpfile # change stderr to a file
ls # you will see no prompt, and no command echo
...
exit # quit sacrificial shell
cat tmpfile # contains PS1 prompt, your commands (and any errors too)
Builtins call (หรืออย่างน้อยควรจะเรียก) builtin_error()
ฟังก์ชั่นภายในเพื่อพิมพ์ข้อผิดพลาดนี้เรียกโดยไม่มีเงื่อนไข fprintf()
ไปยัง stderr
ดังนั้นตัวเลือกมีน้อย
โดยไม่ต้องกระโดดผ่านห่วงหรือปะ bash
วิธีง่ายๆในการเน้นข้อผิดพลาดคือ:
function _t_debug()
{
if [ "${BASH_COMMAND:0:6}" != "_t_err" ]; then
_lastcmd="$BASH_COMMAND"
fi
}
function _t_err()
{
local rc=$1 nn _type _argv
#shift; pipe=($*)
#if [ ${#pipe[*]} -gt 1 ]; then
# for ((nn=1; nn<=${#pipe[*]};nn++));do
# rc=${pipe[$((nn-1))]}
# echo -n "[$nn]=$rc ";
# ((rc >=128)) && echo -n "($((rc-128))) "
# done
#fi
read -a _argv <<< ${_lastcmd}
_type=$(type -t "${_argv[0]}")
if [ -n "$_lastcmd" ]; then
tput setf 4
printf 'Error %s: "%s"' "${_type}" "${_lastcmd:-unknown command}"
tput sgr 0
printf "\n"
fi
((rc >=128)) && echo "[rc=$rc ($((rc-128)))]" ||
echo "[rc=$rc]"
}
trap '_t_err $? ${PIPESTATUS[*]}' ERR
trap '_t_debug' DEBUG
สิ่งนี้ใช้ทุบตี DEBUG
เพื่อดักแคชแต่ละบรรทัดคำสั่งก่อนการดำเนินการและ ERR
ดักเพื่อส่งออกโค้ดส่งคืนหากไม่ใช่ศูนย์ นี้จะไม่แม้ว่าสำหรับทุบตีบางอย่างในตัว (เฉพาะ คำสั่งผสม : while/case/for/if
และอื่น ๆ ดูหน้าคน)
ฉันใช้รูปแบบนี้ในของฉัน .profile
แม้ว่าฉันจะใช้ pipe[]/PIPESTATUS[]
บิตแสดงความคิดเห็นข้างต้นมันเข้ากันไม่ได้กับดัก DEBUG ตามที่ปรากฏด้านบน หากคุณแสดงความคิดเห็นออก trap DEBUG
จากนั้นคุณสามารถใช้มันเพื่อแสดงโค้ดส่งคืนของแต่ละคำสั่งในไปป์ไลน์
(เนื่องจากมีการอ้างอิงถึง command_not_found
เบ็ดฟังก์ชั่นคือ bash-4.0 +.)
คุณอาจต้องการตรวจสอบ stderrred สำหรับวิธีการแก้ปัญหาที่ถาวรมากขึ้น
วิธีการแก้ปัญหาด้านล่างใช้ได้กับสิ่งที่คุณต้องการ:
# whatever_command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
โดยทั่วไปคำสั่งด้านบนจะพิมพ์ออกมา stderr ในสีแดง.
ตรวจสอบภาพหน้าจอด้านล่าง:
ฉันไม่ทราบวิธีการทำให้ถาวรนี้ อย่างไรก็ตามสิ่งนี้ควรให้คำแนะนำแก่คุณอย่างแน่นอน
บางทีคุณสามารถลอง hilite - ฉันคิดว่านี่เป็นหนึ่งในวิธีแก้ปัญหาที่ง่ายที่สุด
ใส่สิ่งนี้ลงในของคุณ ~/.bashrc
หรือ ~/.bash_profile
ไฟล์สำหรับการแก้ไขถาวรหรือหากคุณต้องการให้เป็นการชั่วคราวเพียงพิมพ์สิ่งนี้ลงใน bash
.
command_not_found_handle () {
tput bold;
tput setaf 1;
echo "$0: $1: command not found";
tput sgr0;
}
มันจะทำให้ bash
เอาต์พุตคำสั่งไม่พบข้อผิดพลาดเป็นตัวหนาและสีแดง ไปข้างหน้าและออกไป tput bold;
เพื่อให้ข้อความแสดงข้อผิดพลาดไม่เป็นตัวหนาหรือเปลี่ยน tput setaf 1
ไปยังหมายเลขอื่นสำหรับสีอื่น หวังว่ามันจะช่วย !!
แก้ไข
นี่เป็นเวอร์ชั่นใหม่และปรับปรุงด้านบน
command_not_found_handle () {
echo -e "\e[1;31m$0: $1: command not found\e[0;0m";
return 127; #return bash's error code for command not found
}
แก้ไข 2
If the name is neither a shell function nor a builtin, and contains no slashes, bash
searches each element of the PATH for a directory containing an executable file by that
name. Bash uses a hash table to remember the full pathnames of executable files (see hash
under SHELL BUILTIN COMMANDS below). A full search of the directories in PATH is performed
only if the command is not found in the hash table. If the search is unsuccessful, the
shell searches for a defined shell function named command_not_found_handle. If that
function exists, it is invoked with the original command and the original command's
arguments as its arguments, and the function's exit status becomes the exit status of the
shell. If that function is not defined, the shell prints an error message and returns an
exit status of 127.
เอามาจาก manpage ของทุบตี
ดังนั้นหากวิธีนี้ใช้ไม่ได้ผลอาจเป็นเพราะเปลือกของคุณไม่จริง bash
หรือเป็นรุ่นที่ได้รับการแก้ไขของ bash
.
bash
? ดูการแก้ไข 2
command_not_found_handle () { echo "Error..." }
: ฉันยังได้รับพื้นฐาน-bash: foo: command not found
? ฉันใช้ระบบปฏิบัติการ Mac OSX