Thanks for filing an issue! Please answer the questions below so I can help you.
iTerm2 version: 3.3.9
OS version: OSX 10.15.4, Remote: Amazon Linux
Detailed steps to reproduce the problem:
Connect to a remote Amazon Linux server using ssh. Remote server is running bash 4.2.46. This also happens on a box running Fedora with bash 4.4.23 and locally on macos running bash 5.0.16.
set -o vi
Type a simple command such as 'echo "test"' and run it
Re-type the command (or use history), press esc, hit v to enter vim, type ZZ to save and execute
What happened:
$ echo "test"
echo "test"
_bp_preexec_invoke_exec "$"
test
What should have happened:
$ echo "test"
test
Something appears to be wrong with the __bp_preexec_invoke_exec function in this use case.
What's in your .bash_profile/.profile/.bashrc? It could be a bad interaction between shell integration and another script. Generally, shell integration works best if it is the last one loaded. It is careful not to stomp on existing settings.
I removed my .bashrc and .bash_profile only contains the following line:
test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash"
The issue above still occurs
-bash-4.2$ set -o vi-bash-4.2$ echo "Test"Test-bash-4.2$ echo "Test"echo "Test"__bp_preexec_invoke_exec "$_"Test
In normal usage, the line which loads the shell integration is the last line in .bash_profile which sources .bashrc first, so it is the last thing to load.
Even worse: This will happen for every "line" in every iteration of the command. For example:
$ for f in {1..3}; do echo "This is ${f}"; doneThis is 1This is 2This is 3$ for f in {1..3}; do echo "This is ${f}"; donefor f in {1..3}; do echo "This is ${f}"; done__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"This is 1__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"This is 2__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"This is 3
I wonder if the bash that Amazon uses was compiled with some unusual flags. I've seen weird behavior from bash on LTS Ubunutus.
Logging into an AWS machine is probably too difficult, but Fedora would be doable. What version of Fedora is it? I can easily get VMWare images to play with.
Can you attach your copy of .iterm2_shell_integration.bash here so I can make sure I test with the same one you have? Also, what version of macOS are you on? Anything in your .bash_profile, .profile, or .bashrc? Maybe also attach your ~/Library/Preferences/com.googlecode.iterm2.plist file in case there's something there that makes a difference.
George, I've set up an AWS linux instance and tested to ensure this happens. If you can send me a public ssh key I can add it to the server so you can ssh in and test.
You're welcome! You should be able to log on to justthat.strangled.net using your key and the logon name 'gnachman'
Shell integration is already installed for gnachman and set -o vi is in .bashrc so you won't need to worry about those.
The steps to reproduce the issue are:
type: echo "test"
press esc (to enter vi edit mode)
press v (to edit the command line in vi)
type ZZ to save and run the command. Result:
echo "test"__bp_preexec_invoke_exec "$_"test
press i to get back into insert mode
This happens after each command iteration so something like this...
type: for i in {1..10}; do echo "test"; done
press esc (to enter vi edit mode)
press v (to edit the command line in vi)
type ZZ to save and run the command. Result:
for i in {1..10}; do echo "test"; done__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test__bp_preexec_invoke_exec "$_"__bp_preexec_invoke_exec "$_"test```...results in a lot of noise.
Thank you for setting that up. I stupidly missed the last step of your original description which is why I had so much trouble reproducing it. I can get it to happen now and it sure looks like a bash bug. I've opened a question here:
I'll have a look at the bash code to see if I can make any sense of it (I usually cannot) and will file a bug against bash if I can make a case that it's not somehow intended behavior on their party.
Ok, I did some spelunking and what I found is that when you invoke your editor (v in vi mode or C-x C-e in emacs mode) it runs the fc builtin. For example, fc -e vi to invokes vi. This is done in fc_builtin() which blocks on retval = parse_and_execute (command, "fc", SEVAL_NOHIST); until the editor exits. The last thing it does is echo_input_at_read = 1;, which turns on printing of commands. I guess it does this with the intent of printing out the command you entered so you can see what it's about to execute.
Immediately after setting that flag, it does fc_execute_file() to run the command you just entered in your editor. fc_execute_file() eventually calls parse_and_execute() with the tempfile to run its commands. A side-effect of parsing the commands is to print them out when echo_input_at_read is true. This is fine. The trouble comes next: it runs the debug trap, and the echo_input_at_read flag is still 1. Here's a chunk of the relevant stack trace:
* frame #0: 0x00007fff6d46b20c libsystem_c.dylib`fprintf frame #1: 0x000000010c53a205 bash`shell_getc(remove_quoted_newline=1) at parse.y:2494:6 frame #2: 0x000000010c5384f0 bash`read_token(command=0) at parse.y:3251:23 frame #3: 0x000000010c533f13 bash`yylex at parse.y:2761:19 frame #4: 0x000000010c5307c5 bash`yyparse at y.tab.c:1842:16 frame #5: 0x000000010c530359 bash`parse_command at eval.c:303:7 frame #6: 0x000000010c5c714b bash`parse_and_execute(string=<unavailable>, from_file="debug trap", flags=5) at evalstring.c:364:11 [opt] frame #7: 0x000000010c597a59 bash`_run_trap_internal(sig=32, tag="debug trap") at trap.c:1032:4 frame #8: 0x000000010c597703 bash`run_debug_trap at trap.c:1117:25 frame #9: 0x000000010c54d524 bash`execute_simple_command(simple_command=0x00007fa43b601680, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x00007fa43c000910) at execute_cmd.c:4196:12 frame #10: 0x000000010c54ba3d bash`execute_command_internal(command=0x00007fa43b601660, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x00007fa43c000910) at execute_cmd.c:844:4 frame #11: 0x000000010c5c7300 bash`parse_and_execute(string=<unavailable>, from_file="/var/folders/v3/jxvtby191yj866l8_09rdbxr0000gn/T//bash-fc.65iKNO", flags=16) at evalstring.c:458:17 [opt] frame #12: 0x000000010c5c6b95 bash`_evalfile(filename="/var/folders/v3/jxvtby191yj866l8_09rdbxr0000gn/T//bash-fc.65iKNO", flags=163) at evalfile.c:285:14 [opt] frame #13: 0x000000010c5c8cb5 bash`fc_builtin(list=<unavailable>) at fc.def:468:12 [opt]
After fc_execute_file() returns it calls run_unwind_frame which restores echo_input_at_read to its normal value (0 unless you ran bash --verbose) with set_verbose_flag().
Looking at run_debug_trap() we see something really interesting:
The blame log from https://github.com/bminor/bash shows it was added in bash-5.0 on Jan 17, 2019. The bash project doesn't use git and that commit is a quarter million lines of diff so it's hard to draw any inferences from it :).
I've posted a message to the bug-bash mailing list, which ought to show up in the archive tomorrow:
Looks like this came up recently (https://lists.gnu.org/archive/html/bug-bash/2020-04/msg00016.html) and the fix has been moved into the bash devel branch. I can't find any documentation on their release process, but it appears to be pretty slow. I can't blame them for that; maintaining bash must be an insane burden. Anyway, if you feel brave you can build it from http://git.savannah.gnu.org/cgit/bash.git/log/?h=devel or otherwise wait a few years and get bash 5.1 or whatever they call it :)
I have a workaround but I really don't know if it's a good idea to ship it because modifying bash builtins is sure to have unexpected consequences. It turns out that the v command is a shortcut for the builtin command fc. The following seems to solve the problem: