I have script. I want to do is
- when some command fails (note conditionals not matching must not be considered as fail)
- only when certain command fails script should pause and display user the failed command and ask user if want to edit the command
- if user input "y" then it opens command in vim wherein user would edit the wrong command and resume script with new command.
- or if user input "n" normally continue to next command
need to develop above approach with
So far I deduced following mechanism
trap rerun ERR trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
#maybe using above we can store each command in previous command variable. so when command fails, that command string can be obtained using previous command variable
rerun() { echo "$previous_command" | vim - #OR vim <(echo "$previous_command") }
want a way to echo previous command to vim and let user edit it and execute it.
[ simple way: echo previous command >> tmpfile vi tmpfile #now user will edit it and save and exit then eval "$(cat tmpfile)" ]
But I want a fileless solution no temp file employing ctrl+x ctrl+e programatically
Important Points
We can on rerun
rerun() { echo "$previous_command" | vim - #OR vim <(echo "$previous_command") }
how to execute it after editing in current shell contextalso if command fails second time after rerun function then thar err should not be trapped and continue to next command and log the failed command
Maybe fc command can help edit and execute
So far I deduced below. Add below to beginning of shell script
rerun() { printf "%s\n" "Below Command Failed:" "$previous_command" read -p "Do You Want to Continue execution or edit the failed command.(Y/N)" input if [[ "$input" =~ (y|Y) ]]; then { fc -e vi -1; }; elif [[ -z "$input" ]] || [[ "$input" =~ (n|N) ]]; then :; fi } trap rerun ERR trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
But i haven't tested above. Any more robust solution are welcomed.
Also i want to employ mechanism that when a command fails rerun is executed by trap. But even after rerun if command fails second time then dont execute rerun and continue to next command
To above problem i tried:
rerun() { if [[ -n "$norepeat" ]]; then unset norepeat elif [[ -z "$norepeat" ]]; then printf "%s\n" "Below Command Failed:" "$previous_command" read -p "Do You Want to Continue execution or edit the failed command.(Y/N)" input if [[ "$input" =~ (y|Y) ]]; then { fc -e vi -1; [[ "$?" != "0" ]] && norepeat=1; }; elif [[ -z "$input" ]] || [[ "$input" =~ (n|N) ]]; then norepeat=1; fi } trap rerun ERR trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
Description: On first err the rerun wil be executed and ask user to continue or edit and execute. On "Y" prompt, it will use fc command to execute the last command and test if command executed has no exit status zero i.e, command failed second time and set norepeat=1; since commmand failed second time due to err rerun will be executed again. But this time since norepeat has been set it will not run fc, but will unset norepeat and the script continues to next command. Now if another command fails rerun will be called but since norepeat has been unset it will run fc command.
Havent tested above. Not sure that after fc command $? will actually test the exit code of fc command or the re-edited-re-executed command
Critics and improvements to my approach and any other robust solutions are welcomed. Please Help.
Another thing need is to on command fails second time log it to failed.log #Because on second time fail i am not sure previous_command will be set to "fc commamd" or "re-executed command"
A proposal to above: Inside rerun function we can capture $LINENO
as first command and after fc command while setting norepeat we can echo "$LINENO" >> failed.log
OR sed ''"$LINENO"'p' -En "$0" >> failed.log
As Below (Not sure would work or not
rerun() { failed_lineno="$LINENO" if [[ -n "$norepeat" ]]; then unset norepeat elif [[ -z "$norepeat" ]]; then printf "%s\n" "Below Command Failed:" "$previous_command" read -p "Do You Want to Continue execution or edit the failed command.(Y/N)" input if [[ "$input" =~ (y|Y) ]]; then { fc -e vi -1; [[ "$?" != "0" ]] && { norepeat=1; sed ''"$failed_lineno"'p' -En "$0" >> failed.log; }; elif [[ -z "$input" ]] || [[ "$input" =~ (n|N) ]]; then norepeat=1; fi } trap rerun ERR trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG