Preserving PS1 while in SSH with GitBash? - bash

I have a complicated prompt. Very. I use git-bash for windows.
SSH-ing in on gitbash sends me to the CMD prompt. I know to type ssh -t user#host "bash -l" to get a bash prompt. It works, however, I use a repository called gitstatus to speed up the parsing of the git commands, and sshing in using bash -l calls the PS1 set in /c/cygwin/etc/bash.bashrc (for Mintty), NOT ~/bash.bashrc (for GitBash). This initially seems fine, as I can just copy paste the code from the GitBash *.bashrc to cygwin's. However, the gitstatus repository only works on bash terminals, aka not Cygwin/Mintty, so the prompt when I ssh in appears quite slower in git repos (Mintty doesn't allow gitstatus to be sourced and speed up parsing, once again) than if I was not SSH-ed in and using the GitBash-sourced prompt.
Are there any work arounds for this? I have seen many simnilar questions here but none have provided me a solution.

If you're in my situation, just source the scripts (duh). If you can't execute foo in file x when it should do the same thing as bar in file y, just source bar from file x. It seems obvious but took me a moment.
ALSO: Make sure to run dos2unix.exe on admin command prompt to remove carriage returns every time you make a change.

Related

basic shell commands extremely slow on Git-Bash, sh.exe but fine on Cygwin

When I run basic commands like pwd and cd the command itself executes fast but the console hangs for 1 second before allowing me to execute another command.
I got the latest Git Bash portable and tried
32- and 64-bit
Run as admin
sh.exe instead of git-bash.exe (and Run as admin)
But Cygwin does not have this problem.
In Cygwin, running pwd from the same directory as any Git Bash variant results in equally fast command completion but also there is no console hanging.
My Windows is: Version 10.0.19044 Build 19044
I have nVidia Quadro P3000
UPDATE from comments below:
It appears to be an issue with my Git installation but I chose the defaults so I don't know what it could be.
When I execute PS1='$ ' in Git-Bash, I do not have the the 1-second pause after each command is executed.
UPDATE from comments below
$ echo ${PS1#A}
declare -x PS1='\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[0m\]\n$ '
I did not change anything.
I download a version of portable Git For Windows, launch as admin and type ls, pwd, etc.
I went back to 2.24 but same behavior.
I'm also going to try it on my personal PC since it could be my corporate antivirus that's causing this.
UPDATE
The issue is __git_ps1 and there's an open issue
I think that __git_ps1 is the culprit.
As a test, put following code in /tmp/experiment.sh
if [[ "$(type -t __git_ps1)" == 'function' ]]; then
cd(){
builtin cd "$#"
__GIT_PS1=$('__git_ps1') # Calling original __git_ps1, only when changing directory.
}
__git_ps1_stub(){
echo "$__GIT_PS1" # Now $PS1 will do this echo, instead of calling __git_ps1
}
alias __git_ps1=__git_ps1_stub # __git_ps1_stub will be called in $PS1
cd . # Initialize $__GIT_PS1 for the first time.
fi
Then start a git-bash terminal, and run source /tmp/experiment.sh
If situation improves, you can put the code in ~/.bashrc
You'll need to change other commands (like pushd, popd, etc) if you use them to change directory.
Try first to simplify your PATH when testing your Git bash.
In a CMD, type
set "GH=C:\Program Files\Git"
set "PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0"
set "PATH=%GH%\bin;%GH%\cmd;%GH%\usr\bin;%GH%\mingw64\bin;%GH%\mingw64\libexec\git-core;%PATH%"
Then try again and type bash to enter a shell session.
By default, I get:
$ echo $PS1
\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u#\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[0m\]\n$
And it is quite fast.
(Microsoft Windows 10.0.19044.1586, git version 2.35.1.windows.2)
The problem may be related to slow resolution of computer network names. Since the computer name is involved in the command line. I advise you to add yourhostname and localhost to etc/hostname.
For me it was corrupt page file. Try clearing Windows page file and rebooting. Page file was constantly causing my git bash to hang for 20 seconds with just carriage returns. I've re-enabled page file several times and eventually it happens again. Clearing page file fixed it every time.
I turn page file completely off now and git bash is screaming fast.

Line wrapping in cygwin prompt?

I have looked at duplicate questions. Nothing has worked.
I use Gitbash, and when using Cygwin, I source the gitbash prompt (/Git/etc/bash.bashrc) to display the same prompt. In Gitbash, the prompt works. In cygwin, the output line wraps. For example:
[ "$python_version" ] && python_version='\[\033[95;38;5;227m\]🐍'"${python_version##* } "
This line causes a wrap (only in cygwin) when appended to PS1. The minttyrc and color settings are exactly the same. Removing the color, which I think is the problem, fixes the wrap. However, I believe everything is escaped correctly, and as it doesn't wrap in gitbash, I don't know what the problem is.
The color here seems to be the issue, as removing it fixes it. But why? What is so different about the terminals? I also wonder if it could be an issue with an early escape, but PyCharm's shellcheck says it's all fine.
Wrapping example:
Cygwin:
⬢14.7.0p/new 🐍3.8.3 (venv) ❯
GitBash (ideal output):
~/Desktop/new 🐍3.8.3 ⬢14.7.0 (venv) ❯
It only occurs within the prompt (PS1 variable, aka PROMPT_COMMAND); not when actually typing out commands in the terminal.
Answer: Cygwin is trash (excuse the exaggeration). It has so many utilities but many have encountered bugs like this, and it is really a shame. I uninstalled it, removed its variables from PATH, and with C:\Program Files\Git\bin added to such, I could now ssh in using ssh -t user#host bin "bash -l". This gave me a correct prompt, in ssh or not, with no wrapping; I was able to install other utilities, such as g++, using MinGW. I hope Cygwin gets things sorted out soon, as I debugged in every single way; changed no code, uninstalled it, and then had a successful output.

cd into folders breaks/hangs zsh for minutes using Windows cmd, Powershell, Hyper, and Bash (Ubuntu)

To clarify which I've tried:
Ubuntu bash
Hyper
Powershell
Git bash
cmd
I have installed Ubuntu bash on my Windows 10 PC. When I open ubuntu.exe up and I type zsh after the shell has started, my zsh shell starts up instead, as expected. This is perfectly fine and it does exactly what I want.
The problem: When I do the following sequences:
cd
[TAB]
[ARROW KEYS] (select an item)
ENTER
It should cd into that folder. And it does that, but it literally takes over a minute to do so. CTRL+C to cancel does not work.
Now that I'm in that folder, I can clear the console by typing clear, so that's what I do:
user#user-pc > /mnt/c/folder/otherfolder > GIT-REPO > clear
When I type clear and hit enter, it takes probably 30+ seconds before it clears the window.
I have tried a bunch of themes and a bunch of terminals/command prompts, but none of them work, not even the default one.
I've installed zsh and oh-my-zsh by doing these commands inside the Ubuntu bash shell:
sudo apt-get install zsh
curl -L https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh | bash
Any idea why this odd behavior happens? It looks like it's zsh, because I can easily cd into other folders using all of the above terminals. The problem also happens if I simply cd /mnt/c/folder/otherfolder/ with and without the trailing slash.
Does it only happen in that particular folder? IME, large git repositories can be really slow on zsh+WSL even with the default prompt.

SSH heredoc to run Perl script on another server can't find right paths

I have a Perl program on server_B which uses Perl DBI and 5.010 and runs fine from the server_B terminal. I run it from a shell script which first prepares some arguments and then passes them to the Perl program, all works fine.
I need to run a shell script on server_A that will execute that script on server_B. This is because the Perl program creates several files that I want to SFTP back over to server_A. This is the script I'm running on server_A:
ssh server_B <<- EOF
perl/update.sh
EOF
There is some strange behavior which I'm trying to understand:
The script (update.sh) on server_B runs mysql, which is not installed on server_A (which is why I have to do this whole thing.) If I try to run it on server_B as-is, I can call mysql just like that. But when I run the above script (on server_A) to ssh into server_B and run that script, it doesn't recognize mysql unless I change the file (on server_B) to call the full path /opt/mysql/client/bin/mysql (even though that file is already on server_B with mysql installed) Does this mean server_B is picking up on the PATH variable from server_A instead of using my PATH variable from server_B? Is it trying to run my programs from server_A on the files on server_B? How and why??
If I make the change above it executes the script, but when it hits Perl it says
Perl v5.10.0- required - this is only v5.8.8
Again, 5.10 works fine on server_B but the version of Perl on server_A is 5.8.8.
So I got rid of use 5.010; because it actually wasn't necessary, but then I have a similar problem with my modules (DBI and DBD::mysql). I get:
Can't locate DBI.pm in #INC (#INC contains.. [my Perl PATH from server_A])
at perlfile.pl line 4
I was expecting the ssh heredoc call to update.sh (from server_A) to run exactly as update.sh does if I call it on server_B, but instead it seems like it's trying to use my programs from server_A on server_B, which I find weird. Can anyone help me understand why it's happening? I feel like I'm misunderstanding something fundamental about how ssh works.
server_A is AIX with ksh
server_B is AIX with bash
Edit - since some of you voted to the effect that I haven't done my research, here's what else I've tried. I didn't mention because I don't understand them fully, these are just guesses based on other SO posts & hunches. It'd be disingenuous if I gave the impression I knew what I was talking about.
If this is a duplicate, which question should I be looking at? If this is a "just read the manual situation", which one? What should I look for?
Read man ssh looking for clues related to environment variables, didn't find anything I understood
Tried running with -t
Tried running with -t -t
Did log in remotely with ssh and manually running it - this DOES work
Sourced my .bash_profile in the update script
Tried to re-assign PATH as the remote server's PATH when ssh
Tried using a different delimiter for the heredoc
Tried < instead of <<
Tried without the "-"
Edit 2 with Saigo's help below I determined that when in interactive ssh, if I echo $PATH I do get the target server's $PATH, but in a shell script I don't. That led me to this:
https://serverfault.com/questions/643333/different-bash-path-variables-when-using-ssh-script-vs-interactive-ssh
where I found out that scripted ssh doesn't call .bashrc, but interactive ssh does. So it looks like I was on the right track trying to source .bash_profile inside the scripted SSH heredoc, just need .bashrc not .bash_profile - however I don't have a .bashrc on the target server. I do have .profile but when I source that, I get an error stating it's for interactive bash sessions only. So now I'm just trying to find whatever file would contain my $PATH variable because it's apparently not .bashrc as there isn't one in there.
Edit 3 - tried hard-coding the PATH variable into a file and sourcing that and even then when I echo $PATH I get the origin server's PATH variable. It is reading the file in correctly, I also assigned another test variable and echoed that as part of the script. I tried sourcing /etc/profile and no luck.
I found a solution that works perfectly. I wasn't able to get it to work with ~/.bashrc, ~/.bash_profile, or ~/.ssh/rc but still not sure why it's not picking up my environment variables even with sourcing these.
Since it works when I manually ssh in and then run the commands one-by-one, I used these arguments to run ssh in a forced interactive login.
ssh server_B bash --login -i "~/perl/update.sh"
See these for more:
https://superuser.com/questions/564926/profile-is-not-loaded-when-using-ssh-ubuntu
https://unix.stackexchange.com/questions/46143/why-bash-unable-to-find-command-even-if-path-is-specified-properly
Hope this is useful for someone in the future. Thank you for your assistance Saigo.

How to make a "macro" to automate some bash commands in OS X Terminal?

I'm pretty decent with bash and UNIX commands, and the Terminal app, but I'm wondering, is there a way to make a "macro" (maybe that's the wrong word!) to automate some tasks?
For example, to get into my current project directory, I type:
$ cd ~/Documents/College/F13/CS362/lab3/os-lab-3
And then I immediately do
$ hg pull
(password)
And then
$ hg update
So is there a way to even automate that first step of the cd call? I've never tried anything like that before, not sure if what I'm going for is even possible.
Bonus: is there a way to have the macro enter my password when prompted as well? Security/privacy is not really an issue here, there's no thermonuclear codes hiding around in the repo.
The name generally used in this context (a macro in bash) is shell script. To automate the commands from your post you would need to create a file with a name like 'myscript.sh' with the following contents:
#!/bin/bash
cd ~/Documents/College/F13/CS362/lab3/os-lab-3
hg pull
hg update
The first line of the script is a hashbang. This is a special comment line which indicates that file should be executed using the indicated program. Bash in this case.
To run the script first ensure that it is executable by running the following command:
chmod +x myscript.sh
From there in terminal window just run the script by specifying the path to it:
./myscript.sh
Don't put passwords into shell scripts though! It is a bad habit. For authentication with Mercurial an ssh key pair is the best way to go. The ssh key can be loaded into OSX's keychain, so you won't have to type anything when you run the script. You'll also need to add the public portion of your ssh key pair to the list of authorized hosts on the remote Mercurial repository.

Resources