Cygwin inherits environment variables from Windows sometimes - windows

If I set the environment variable CVSROOT in Windows and give it a value like cvsserver:/home/cvs, if then
1) open Windows CMD shell and do "echo %CVSROOT%", I get "cvsserver:home/cvs"
2) open Cygwin bash shell and do "echo $CVSROOT", I get "cvsserver:home/cvs"
3) from Linux, ssh to the machine and do "echo $CVSROOT", I get nothing.
If I want the ssh session to have a value for CVSROOT, I need to insert it into the .bashrc.
Is there something that can be done so that the ssh session also inherits the environment variable from Windows?
edit:
4) from Linux, do
ssh machine "printenv CVSROOT"
with the environment variable set in .bashrc, I get nothing. At an interactive prompt, I get the variable value, but this way gives nothing.

I found a nice solution here: http://www.smithii.com/node/44
It looks for system variable in registry and sets variables in session opened via ssh.
Then, call the small piece of script from your ssh client (while connecting to your cygwin server), as this:
ssh $WINDOWSUSER#$WINDOWSBUILDSERVER "source /etc/profile ; echo $CVSROOT "

OK, I've figured it out...
For whatever reason, the bash shell is not inheriting the CVSROOT variable that is set on the system. I need to put this line
export CVSROOT=cvsserver:/home/cvs
into both the .bashrc and the .bash_profile files.
The line is needed in the .bashrc file so that non-interactive logins will get the CVSROOT variable. For example:
ssh machine "printenv CVSROOT"
needs this line in the .bashrc file so that CVSROOT exists.
The line is needed in the .bash_profile file so that interactive logins will get the CVSROOT variable. For example:
ssh machine
printenv CVSROOT

If you have your SSH Service running on a windows box (I'm assuming you do) and it's via Cygwin.
The service seems to take a snapshot of the environment variables when it starts up and doesn't refresh them.
Restarting the service should be enough.

One thing is Windows->Cygwin the other thing is ssh
have you tried forwarding your Windows variable to your linux explicitly:
ssh -t user#host "export CVSROOT=%CVSROOT%;/bin/bash --login"

Restarting your computer will solve this problem. Environment variable changes don’t just propagate to all your running programs.

I hit upon the same problem. Got this working by setting the variable like this:
ssh machine "export MYVARIABLE=1 && printenv MYVARIABLE"

Related

How to SSH from local linux into specific directory on windows 10 remote

I want to ssh from my local linux computer into a specific directory on a windows 10 remote. The shell that is used on the remote is git bash. I don't want to keep changing the directory every time I log into my remote using ssh.
for linux remotes this is easily done using something like this:
ssh -t user#x.x.x.x "cd /targetDir ; \$SHELL --login"
The question is how can the same thing be achieved for Windows 10 remotes? If nothing else works I would also accept changing the default entry point in git bash for any ssh sessions on the remote.
Please note that I am not looking for help setting up ssh (already works). I just want to jump right into a specific directory when a session is started.
I was able to figure this thing out myself. The following command gets the job done. Using double and single quotes together is required to make it work (in no particular order).
ssh -t user#x.x.x.x "'cd /targetDir ; bash'"

How to read target environment variables in shell script ssh

I have a shell script which ssh to a server.
ssh -t user#x.x.x.x << "EOT"
echo $ENVIRONMENT_VARIABLE
set +e
EOT
The $ENVIRONMENT_VARIABLE is already set in the server. However in the script it cannot read its value. How can I make it so that in the script it can read its value?
It looks like you don't have your environment fully set when in the SSH session.
It depends on the type of session opened (interactive, login shell, ...).
It also depends on your Linux and the shell you are using.
You can check this topic on the subject.

add ssh key once per login instead of once per bash

I want to use ssh passwordless-login using authentication-key-pairs.
I added
eval `ssh-agent -s`
ssh-add ~/.ssh/my_p_key
to ~/.profile. This doesn't work. If I use the ~/.bashrc it works fine.
Why do I have to set this every time I call a bash instead of every time the user logges in. I could not find any explanation.
Is there no better way to configure this?
The answer below solved my problem and for me it looks like a very legit solution.
Add private key permanently with ssh-add on Ubuntu
The
eval `ssh-agent -s`
sets the environment of the process. If you are using a window manager e.g. on a linux machine then the window manager will likely have a possibility to run a program like e.g. your ssh-agent on startup and passing the environment down to all processes started there, so all your terminal windows/tabs will allow you a passwordless login. The exact location, configuration and behaviour depends on the desktop/wm used.
If you are on a non-window-system, then you might look at the output of the ssh-agent call and paste that into all shells you open, however that may be as complicated as entering your password. The output will likely set something like
SSH_AGENT_PID=4041
SSH_AUTH_SOCK=/tmp/ssh-WZANnlaFiaBt/agent.3966
and you can access pw-less in all places where you set these
Just adding "IdentityFile ~/.ssh/config" to my .ssh/config did not work for me. I had to also add "AddKeysToAgent yes" to that file.
I think this extra line is necessary because gnome-Keyring loads my key but it has a bug that prevents it from being forwarded to the machine I ssh into.
Edit: After upgrading to Ubuntu 20.04, new terminals that I started could not access the ssh-agent. I had to add eval (ssh-agent -c) &>/dev/null to my ~/.config/fish/config.fish file.

Injecting bash prompt to remote host via ssh

I have a fancy prompt working well on my local machine. However, I'm logging to multiple machines, on different accounts via ssh. I would love to have my prompt synchronized everywhere by ssh command itself.
Any idea how to get that? In many cases I'm accessing machines using root account and I can't change permanently any settings there. I want the prompt synchronized.
In principle this is just setting variable PS1.
Try this :
ssh -l root host -t "bash --rcfile /path/to/special/bashrc"
maybe /path/to/special/bashrc can be /tmp/myrc by example

How can I ssh directly to a particular directory?

I often have to login to one of several servers and go to one of several directories on those machines. Currently I do something of this sort:
localhost ~]$ ssh somehost
Welcome to somehost!
somehost ~]$ cd /some/directory/somewhere/named/Foo
somehost Foo]$
I have scripts that can determine which host and which directory I need to get into but I cannot figure out a way to do this:
localhost ~]$ go_to_dir Foo
Welcome to somehost!
somehost Foo]$
Is there an easy, clever or any way to do this?
You can do the following:
ssh -t xxx.xxx.xxx.xxx "cd /directory_wanted ; bash --login"
This way, you will get a login shell right on the directory_wanted.
Explanation
-t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services.
Multiple -t options force tty allocation, even if ssh has no local tty.
If you don't use -t then no prompt will appear.
If you don't add ; bash then the connection will get closed and return control to your local machine
If you don't add bash --login then it will not use your configs because its not a login shell
You could add
cd /some/directory/somewhere/named/Foo
to your .bashrc file (or .profile or whatever you call it) at the other host. That way, no matter what you do or where you ssh from, whenever you log onto that server, it will cd to the proper directory for you, and all you have to do is use ssh like normal.
Of curse, rogeriopvl's solution works too, but it's a tad bit more verbose, and you have to remember to do it every time (unless you make an alias) so it seems a bit less "fun".
My preferred approach is using the SSH config file (described below), but there are a few possible solutions depending on your usages.
Command Line Arguments
I think the best answer for this approach is christianbundy's reply to the accepted answer:
ssh -t example.com "cd /foo/bar; exec \$SHELL -l"
Using double quotes will allow you to use variables from your local machine, unless they are escaped (as $SHELL is here). Alternatively, you can use single quotes, and all of the variables you use will be the ones from the target machine:
ssh -t example.com 'cd /foo/bar; exec $SHELL -l'
Bash Function
You can simplify the command by wrapping it in a bash function. Let's say you just want to type this:
sshcd example.com /foo/bar
You can make this work by adding this to your ~/.bashrc:
sshcd () { ssh -t "$1" "cd \"$2\"; exec \$SHELL -l"; }
If you are using a variable that exists on the remote machine for the directory, be sure to escape it or put it in single quotes. For example, this will cd to the directory that is stored in the JBOSS_HOME variable on the remote machine:
sshcd example.com \$JBOSS_HOME
SSH Config File
If you'd like to see this behavior all the time for specific (or any) hosts with the normal ssh command without having to use extra command line arguments, you can set the RequestTTY and RemoteCommand options in your ssh config file.
For example, I'd like to type only this command:
ssh qaapps18
but want it to always behave like this command:
ssh -t qaapps18 'cd $JBOSS_HOME; exec $SHELL'
So I added this to my ~/.ssh/config file:
Host *apps*
RequestTTY yes
RemoteCommand cd $JBOSS_HOME; exec $SHELL
Now this rule applies to any host with "apps" in its hostname.
For more information, see http://man7.org/linux/man-pages/man5/ssh_config.5.html
I've created a tool to SSH and CD into a server consecutively – aptly named sshcd. For the example you've given, you'd simply use:
sshcd somehost:/some/directory/somewhere/named/Foo
Let me know if you have any questions or problems!
Based on additions to #rogeriopvl's answer, I suggest the following:
ssh -t xxx.xxx.xxx.xxx "cd /directory_wanted && bash"
Chaining commands by && will make the next command run only when the previous one was successful (as opposed to using ;, which executes commands sequentially). This is particularly useful when needing to cd to a directory performing the command.
Imagine doing the following:
/home/me$ cd /usr/share/teminal; rm -R *
The directory teminal doesn't exist, which causes you to stay in the home directory and remove all the files in there with the following command.
If you use &&:
/home/me$ cd /usr/share/teminal && rm -R *
The command will fail after not finding the directory.
In my very specific case, I just wanted to execute a command in a remote host, inside a specific directory from a Jenkins slave machine:
ssh myuser#mydomain
cd /home/myuser/somedir
./commandThatMustBeRunInside_somedir
exit
But my machine couldn't perform the ssh (it couldn't allocate a pseudo-tty I suppose) and kept me giving the following error:
Pseudo-terminal will not be allocated because stdin is not a terminal
I could get around this issue passing "cd to dir + my command" as a parameter of the ssh command (to not have to allocate a Pseudo-terminal) and by passing the option -T to explicitly tell to the ssh command that I didn't need pseudo-terminal allocation.
ssh -T myuser#mydomain "cd /home/myuser/somedir; ./commandThatMustBeRunInside_somedir"
I use the environment variable CDPATH
going one step further with the -t idea. I keep a set of scripts calling the one below to go to specific places in my frequently visited hosts. I keep them all in ~/bin and keep that directory in my path.
#!/bin/bash
# does ssh session switching to particular directory
# $1, hostname from config file
# $2, directory to move to after login
# can save this as say 'con' then
# make another script calling this one, e.g.
# con myhost repos/i2c
ssh -t $1 "cd $2; exec \$SHELL --login"
My answer may differ from what you really want, but I write here as may be useful for some people. In my solution you have to enter into the directory once and then every new ssh session goes to the same dir (after the first logout).
How to ssh to the same directory you have been in your last login.
(I assume you use bash on the remote node.)
Add this line to your ~/.bash_logout on the remote node(!):
echo $PWD > ~/.bash_lastpwd
and these lines to the ~/.bashrc file (still on the remote node!)
if [ -f ~/.bash_lastpwd ]; then
cd $(cat ~/.bash_lastpwd)
fi
This way you save your current path on every logout and .bashrc put you into that directory after login.
ps: You can tweak it further like using the SSH_CLIENT variable to decide to go into that directory or not, so you can differentiate between local logins and ssh or even between different ssh clients.
Another way of going to directly after logging in is create "Alias". When you login into your system just type that alias and you will be in that directory.
Example : Alias = myfolder '/var/www/Folder'
After you log in to your system type that alias (this works from any part of the system)
this command if not in bashrc will work for current session. So you can also add this alias to bashrc to use that in future
$ myfolder => takes you to that folder
I know this has been answered ages ago but I found the question while trying to incorporate an ssh login in a bash script and once logged in run a few commands and log back out and continue with the bash script. The simplest way I found which hasnt been mentioned elsewhere because it is so trivial is to do this.
#!/bin/bash
sshpass -p "password" ssh user#server 'cd /path/to/dir;somecommand;someothercommand;exit;'
Connect With User
In case if you don't know this, you can use this to connect by specifying both user and host
ssh -t <user>#<Host domain / IP> "cd /path/to/directory; bash --login"
Example: ssh -t admin#test.com "cd public_html; bash --login"
You can also append the commands to be executed on every login by appending it in the double quotes with a ; before each command
Unfortunately, the suggested solution (of #rogeriopvl) doesn't work when you use multiple hops, so I found another one.
On remote machine add into ~/.bashrc the following:
[ "x$CDTO" != "x" ] && cd $CDTO
This allows you to specify the desired target directory on command line in this way:
ssh -t host1 ssh -t host2 "CDTO=/desired_directory exec bash --login"
Sure, this way can be used for a single hop too.
This solution can be combined with the usefull tip of #redseven for greater flexibilty (if no $CDTO, go to saved directory, if exists).
SSH itself provides a means of communication, it does not know anything about directories. Since you can specify which remote command to execute (this is - by default - your shell), I'd start there.
simply modify your home with the command:
usermod -d /newhome username

Resources