Aug. 8th, 2018 09:51 pm
bash debugger
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Bash debugger базований на редакторі vim
Огляд
Ми часто використовуємо опції bash для того, щоб налагоджувати скрипти, але іноді це не комфортно.
Якщо ви володієте редактором vim, тоді ви зможете легко і якісно дебажити скрипти прямо з редактора!
Вам треба виконати всього дві дії:
1. Додати команди до ~/.vimrc
2. Створити скрипт debugger.sh у теці ~/.vim
Що може даний налагоджувач?
1. Порядкове виконання скрипту
2. Переглядати значення вказаних змінних після кожного кроку виконання
3. Створювати місця зупинки виконання скрипту візуально у редакторі
4. Виконувати скрипт до наступного місця зупинки(якщо воно є)
5. Вмикання.вимикання трасування всередині функцій
6. Виконувати скрипт без налагоджувача
7. Видаляти всі помітки(місця зупинки, перемикання трасування функцій)
Клавіші керування налагоджувачем
F9 - Видалення всіх міток
F8 - Виконання скрипту без налагоджувача
F7 - Виконання скрипту з налагоджувачем
F6 - Показати/приховати вікно з змінними для стеження. Кожна змінна має бути визначена без пропусків, {}, $, тощо.
Приклад:
A
B[1]
C[@]
F5 - Вставити/прибрати місце зупинки виконання скрипту в даному рядку..
F4 - Увімкнути/вимкнути трасування функцій.
Як встановити налагоджувач?
1. Додайте наступні рядки до ~/.vimrc:
:set number
" Underline current line
augroup CursorLine
au!
au VimEnter,WinEnter,BufWinEnter * setlocal cursorline
au WinLeave * setlocal nocursorline
augroup END
" Write&Quit to ~/.vim/variables if it lost focus
augroup VariablesFile
au WinLeave ~/.vim/variables wq
augroup END
" Trace script
fu! Trace()
" Save output of 'sign place' to file
redir > ~/.vim/places
execute "silent sign place file=" . expand("%:p")
redir end
" Save script to temporary file
execute ":w! ~/.vim/bash.debug.sh"
" Run debugger
execute ":! ~/.vim/debuger.sh"
endfunction
" Run script w/o trace
fu! Execute()
silent execute ":!clear"
" Save script to temporary file
execute ":w! ~/.vim/bash.debug.sh"
" Set executing permitions
silent execute ":! chmod 755 ~/.vim/bash.debug.sh"
" Run script
execute ":! ~/.vim/bash.debug.sh"
" Remove temporary script
silent execute ":! rm -f ~/.vim/bash.debug.sh"
endfunction
" Show/hide window with variables
fu! Variables()
" If current file is './vim/variables'
if expand('%:p:h:t') == ".vim"
if expand('%:t') == "variables"
" Save&Quit
execute ":wq!"
else
" Open new window
copen
" Load file with variables
execute ":e ~/.vim/variables"
endif
else
" Open new window
copen
" Load file with variables
execute ":e ~/.vim/variables"
endif
endfunction
" Enable/Disable breakpoint
fu! Breakpoint()
" Get current line
let currentrow = line(".")
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Save output of 'sign place' to file
redir >~/.vim/places
execute ":silent sign place file=" . expand("%:p")
redir end
" Parse file and save sign's name to variable signname
let signname=system("grep '=".currentrow.".*id=.*breakpoint' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
if empty(signname)
" If not exist sign name in current line
" Define breakpoint
execute ":sign define breakpoint" . currentrow . " text=BP texthl=Search linehl=Search"
" Place sign to current line
execute ":sign place ".currentrow." line=".currentrow." name=breakpoint".currentrow." file=".expand("%:p")
else
" If exist sign name in current line then undefine it
exec ":sign undefine ".signname
endif
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Redraw screen
redraw!
endfunction
" Enable/Disable function trace
fu! FuncTrace()
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Save output of 'sign place' to file
redir >~/.vim/places
execute ":silent sign place file=" . expand("%:p")
redir end
" Parse file and save sign's name to variable signname
let signname=system("grep '=1.*id=1.*functrace' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
if empty(signname)
" If not exist sign name in current line
" Define breakpoint
execute ":sign define functrace text=FT texthl=Error"
execute ":sign place 1 line=1 name=functrace file=" . expand("%:p")
else
" If exist sign name in current line then undefine it
execute ":sign undefine functrace"
endif
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Redraw screen
redraw!
endfunction
" Unmark all signs
fu! Unmark()
" Remove all signs
execute ":sign unplace *"
" Redraw screen
redraw!
endfunction
" Undefine all marks
nmap :call Unmark()
" Run script without debuging
nmap :call Execute()
" Run script with debuging
nmap :call Trace()
" Show or hide variables list
nmap :call Variables()
" Mark/Unmark BreakPoint
nmap :call Breakpoint()
" Mark/Unmark Function trace
nmap :call FuncTrace()
:set number та augroup CursorLine блок можуть бути видаленими. Але з ними зручніше працювати у редакторі.
2. Створіть скрипт debugger.sh в теці ~/.vim/
#!/bin/bash
########
# Bash debugger for Vim v. 1.0
# Created by Oleksandr Mishchenko (c) 2018
# sasha.mishchenko@gmail.com
# Published under GPL license
########
clear
echo Executing in trace mode.
echo "Press 'Space' key to execute one line, Press 'g' key to execute to next break point."
if grep functrace ~/.vim/places &>/dev/null
then
sed "1a set -o functrace;trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
else
sed "1a trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
fi
rm -f ~/.vim/bash.debug.sh &>/dev/null
chmod 700 ~/.vim/bash.debug2.sh
~/.vim/bash.debug2.sh
Встановіть права на виконання скрипта:
chmod 755 debugger.sh
Особливості
1. Поки налагоджувач працює лише для одного скрипта. Якщо паралельно налагоджувати 2 скрипти під одним користувачем, то у них будуть спільні місця зупинки, змінні спостереження, тощо.
Огляд
Ми часто використовуємо опції bash для того, щоб налагоджувати скрипти, але іноді це не комфортно.
Якщо ви володієте редактором vim, тоді ви зможете легко і якісно дебажити скрипти прямо з редактора!
Вам треба виконати всього дві дії:
1. Додати команди до ~/.vimrc
2. Створити скрипт debugger.sh у теці ~/.vim
Що може даний налагоджувач?
1. Порядкове виконання скрипту
2. Переглядати значення вказаних змінних після кожного кроку виконання
3. Створювати місця зупинки виконання скрипту візуально у редакторі
4. Виконувати скрипт до наступного місця зупинки(якщо воно є)
5. Вмикання.вимикання трасування всередині функцій
6. Виконувати скрипт без налагоджувача
7. Видаляти всі помітки(місця зупинки, перемикання трасування функцій)
Клавіші керування налагоджувачем
F9 - Видалення всіх міток
F8 - Виконання скрипту без налагоджувача
F7 - Виконання скрипту з налагоджувачем
F6 - Показати/приховати вікно з змінними для стеження. Кожна змінна має бути визначена без пропусків, {}, $, тощо.
Приклад:
A
B[1]
C[@]
F5 - Вставити/прибрати місце зупинки виконання скрипту в даному рядку..
F4 - Увімкнути/вимкнути трасування функцій.
Як встановити налагоджувач?
1. Додайте наступні рядки до ~/.vimrc:
:set number
" Underline current line
augroup CursorLine
au!
au VimEnter,WinEnter,BufWinEnter * setlocal cursorline
au WinLeave * setlocal nocursorline
augroup END
" Write&Quit to ~/.vim/variables if it lost focus
augroup VariablesFile
au WinLeave ~/.vim/variables wq
augroup END
" Trace script
fu! Trace()
" Save output of 'sign place' to file
redir > ~/.vim/places
execute "silent sign place file=" . expand("%:p")
redir end
" Save script to temporary file
execute ":w! ~/.vim/bash.debug.sh"
" Run debugger
execute ":! ~/.vim/debuger.sh"
endfunction
" Run script w/o trace
fu! Execute()
silent execute ":!clear"
" Save script to temporary file
execute ":w! ~/.vim/bash.debug.sh"
" Set executing permitions
silent execute ":! chmod 755 ~/.vim/bash.debug.sh"
" Run script
execute ":! ~/.vim/bash.debug.sh"
" Remove temporary script
silent execute ":! rm -f ~/.vim/bash.debug.sh"
endfunction
" Show/hide window with variables
fu! Variables()
" If current file is './vim/variables'
if expand('%:p:h:t') == ".vim"
if expand('%:t') == "variables"
" Save&Quit
execute ":wq!"
else
" Open new window
copen
" Load file with variables
execute ":e ~/.vim/variables"
endif
else
" Open new window
copen
" Load file with variables
execute ":e ~/.vim/variables"
endif
endfunction
" Enable/Disable breakpoint
fu! Breakpoint()
" Get current line
let currentrow = line(".")
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Save output of 'sign place' to file
redir >~/.vim/places
execute ":silent sign place file=" . expand("%:p")
redir end
" Parse file and save sign's name to variable signname
let signname=system("grep '=".currentrow.".*id=.*breakpoint' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
if empty(signname)
" If not exist sign name in current line
" Define breakpoint
execute ":sign define breakpoint" . currentrow . " text=BP texthl=Search linehl=Search"
" Place sign to current line
execute ":sign place ".currentrow." line=".currentrow." name=breakpoint".currentrow." file=".expand("%:p")
else
" If exist sign name in current line then undefine it
exec ":sign undefine ".signname
endif
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Redraw screen
redraw!
endfunction
" Enable/Disable function trace
fu! FuncTrace()
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Save output of 'sign place' to file
redir >~/.vim/places
execute ":silent sign place file=" . expand("%:p")
redir end
" Parse file and save sign's name to variable signname
let signname=system("grep '=1.*id=1.*functrace' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
if empty(signname)
" If not exist sign name in current line
" Define breakpoint
execute ":sign define functrace text=FT texthl=Error"
execute ":sign place 1 line=1 name=functrace file=" . expand("%:p")
else
" If exist sign name in current line then undefine it
execute ":sign undefine functrace"
endif
" Remove file
silent execute ":! rm -f ~/.vim/places"
" Redraw screen
redraw!
endfunction
" Unmark all signs
fu! Unmark()
" Remove all signs
execute ":sign unplace *"
" Redraw screen
redraw!
endfunction
" Undefine all marks
nmap
" Run script without debuging
nmap
" Run script with debuging
nmap
" Show or hide variables list
nmap
" Mark/Unmark BreakPoint
nmap
" Mark/Unmark Function trace
nmap
:set number та augroup CursorLine блок можуть бути видаленими. Але з ними зручніше працювати у редакторі.
2. Створіть скрипт debugger.sh в теці ~/.vim/
#!/bin/bash
########
# Bash debugger for Vim v. 1.0
# Created by Oleksandr Mishchenko (c) 2018
# sasha.mishchenko@gmail.com
# Published under GPL license
########
clear
echo Executing in trace mode.
echo "Press 'Space' key to execute one line, Press 'g' key to execute to next break point."
if grep functrace ~/.vim/places &>/dev/null
then
sed "1a set -o functrace;trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
else
sed "1a trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
fi
rm -f ~/.vim/bash.debug.sh &>/dev/null
chmod 700 ~/.vim/bash.debug2.sh
~/.vim/bash.debug2.sh
Встановіть права на виконання скрипта:
chmod 755 debugger.sh
Особливості
1. Поки налагоджувач працює лише для одного скрипта. Якщо паралельно налагоджувати 2 скрипти під одним користувачем, то у них будуть спільні місця зупинки, змінні спостереження, тощо.
2. Місця зупинки не діють на командах return, fi, then, else та інших складених bash командах. Це зумовлене тим, що так працює обробка сигналу DEBUG в команді trap в bash. Також ви не зможете зупинити виконання скрипту на рядку, що не містить команд, або містить лише коментарі. При потребі зупинитися в даних місцях, можете тимчасово ставити команду : . Дана команда нічого не робить, проте на ній налагоджувач може зупинятися.
3. Налагоджувач не відслідковує зміст скрипту. Тобто якщо в редакторі буде конфігураційний файл і ви його виконаєте, то він буде переданий інтерпретатору bash на виконання і буде ним відповідно оброблений.
no subject
Таким чайникам, як я, які через усі Башеві конструкції продираються як через тернії, таке дуже корисно. Дякую!
Ще б якби хтось причепив його плугіном до far2l — ващє була б красота. Autocomplete туди, нарешті, приліплено десь півроку тому, працює.