In the machine 10.10.99.10, there is an ~/.bashrc who has the following line to set a variable.
var="hello"
When I use ssh user#10.10.99.10: echo ${var}, ${var} is empty.
So I guess that the ~/.bashrc is not sourced before ssh's command is executed.
I try ssh user#10.10.99.10: source ~/.bashrc; echo ${var} but nothing changed.
How can I source the ~/.bashrc before ssh's command is executed?
I find the reason.
There are following lines in the head of .bashrc
case $- in
*i*) ;;
*) return;;
esac
I echo $- which is hBc, so it just returns.
I comment these lines and all works.
My ~/.bashrc contains this line:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
I comment this line, and source works as expected.
Related
Something I love about VS Code is that when I am using a terminal in WSL, I can run code file.txt, and it will open that file with VS Code on my local using the WSL remote extension.
Is it possible to do a similar thing with SSH? I.e., if I am SSH'ed into a remote host, is it possible to set things up so that running code file.txt will open VS Code on my local machine, connected via the remote SSH extension to open that file?
I found much better & simple answer thanks to this post.
Simply create new script file named code with below contents & put file under any folder from $PATH. (echo $PATH to see what folders you can use)
#! /usr/bin/env zsh
local max_retry=10
for i in {1..$max_retry}
do
local script=$(echo ~/.vscode-server/bin/*/bin/remote-cli/code(*oc[$i]N))
if [[ -z ${script} ]]
then
echo "VSCode remote script not found"
exit 1
fi
local socket=$(echo /run/user/$UID/vscode-ipc-*.sock(=oc[$i]N))
if [[ -z ${socket} ]]
then
echo "VSCode IPC socket not found"
exit 1
fi
export VSCODE_IPC_HOOK_CLI=${socket}
${script} $# > /dev/null 2>&1
if [ "$?" -eq "0" ]; then
exit 0
fi
done
echo "Failed to find valid VS Code window"
Bash version
#! /bin/bash
max_retry=10
for i in $(seq 1 $max_retry)
do
recent_folder=$(ls ~/.vscode-server/bin/ -t | head -n$i)
script=$(echo ~/.vscode-server/bin/$recent_folder/bin/remote-cli/code)
if [[ -z ${script} ]]
then
echo "VSCode remote script not found"
exit 1
fi
socket=$(ls /run/user/$UID/vscode-ipc-* -t | head -n$i)
if [[ -z ${socket} ]]
then
echo "VSCode IPC socket not found"
exit 1
fi
export VSCODE_IPC_HOOK_CLI=${socket}
${script} $#
if [ "$?" -eq "0" ]; then
exit 0
fi
done
echo "Failed to find valid VS Code window"
Update
Above script doesn't work with recent updates. I had to change first line to
local script=$(echo ~/.vscode-server/bin/*/bin/remote-cli/code(*oc[1]N))
Update2
Original script may fail if recently opened ssh window is closed, yet there is another SSHed window open. I have enhanced the script to enable retrying the command with recent N(default 10) windows.
You shouldn't have to do anything. VSCode automatically sets the path/PATH to the code in the path/PATH environment variable depending on your shell. See this response. You might be overwriting your path/PATH like I was. I was accidentally overwriting path in ~/.cshrc and PATH in ~/.bashrc and was running into the same issue. After fixing it, I can run code on the command line. which code returns the location of the command.
Until I spent time to figure it out, I was using the two methods mentioned below. Both of which worked for me in bash; you can modify it for your shell as you see fit. But really fix your path/PATH rather than using these methods.
Adding location of code to the PATH in ~/.bashrc
export PATH=${VSCODE_GIT_ASKPASS_NODE%/*}/bin:$PATH
OR
Setting alias to code in ~/.bashrc
alias code="${VSCODE_GIT_ASKPASS_NODE%/*}/bin/code"
More on path vs. PATH here and here
Yes, sort of.
From a VSCode terminal run the command
env | grep VSCODE_IPC_HOOK_CLI
then copy-and-paste that line that line with export into your ssh terminal.
After that, you should be able to run code from your ~/.vscode-server/bin/XXX/bin directory.
VSCode terminal
SSH terminal
Update:
You can to automate this with a .bashrc and .profile to place the IPC code into a temp file, and source that when you do your ssh login.
For example, this works for me...
Append this to ~/.bashrc
#
if [ "$VSCODE_IPC_HOOK_CLI" != "" ]; then
cat >$HOME/.vscode_env.sh <<EOF
#
if [ "\$VSCODE_IPC_HOOK_CLI" = "" ]; then
export VSCODE_IPC_HOOK_CLI="$VSCODE_IPC_HOOK_CLI"
alias code="${VSCODE_GIT_ASKPASS_NODE%/*}/bin/code"
fi
EOF
fi
And append this to your ~/.profile
[ -f $HOME/.vscode_env.sh ] && . $HOME/.vscode_env.sh
(There may be more elegant ways. And you still have to start at least 1 terminal in your remote VSCode session.)
this works to me
if [[ -n "$SSH_CLIENT" || -n "$SSH_TTY" ]]; then
local script=$(echo ~/.vscode-server/bin/*/bin/remote-cli/code(*oc[1]N))
if [[ -z ${script} ]]
then
echo "VSCode remote script not found"
exit 1
fi
local socket=$(echo /run/user/$UID/vscode-ipc-*.sock(=oc[1]N))
if [[ -z ${socket} ]]
then
echo "VSCode IPC socket not found"
exit 1
fi
export VSCODE_IPC_HOOK_CLI=${socket}
alias code=${script}
fi
Use the below commands to open a folder or a file on the remote terminal.
Note: vscode-server must be already installed on the remote host (It would be, if you have already connected to it). Also the absolute path has to be specified for the file or folder. Use -n to launch in new window,-r to reuse same window.
code --folder-uri <absolute-path>
code --file-uri <absolute-path-file-name>
Example:
code -r --folder-uri /home/myscripts/src
code -n --file-uri /home/myscripts/src/math/sample.py
It's my first time doing something with bash-programming. As a first example I'm trying to source my .bashrc from my .bash_profile - even when ~/.bashrc is a symbolic link.
.bash_profile:
if [ -f ~/.bashrc ] && ! [ -L ~/.bashrc ]
then
# ~/.bashrc is a regular file. Source it!
source ~/.bashrc
echo "~/.bashrc found."
elif [ -L ~/.bashrc ]
then
# ~/.bashrc is a symbolic link.
# Recursivly follow symbolic links.
location="~/.bashrc"
while [ -L $location ]
do
# QUESTION: Control-Flow never reaches this point.
# Follow link on macOS.
location="$(readlink $path)"
done
# Check if final target is regular file. Source it!
if [ -f $location ]
then
source $location
echo "Symlink to .bashrc found."
fi
else
echo "No valid .bashrc found."
fi
This is what I expect my code to do:
If ~/.bashrc is not a symbolic link, but a regular file: Source it.
Otherwise if ~/.bashrc is a symbolic link:
Follow the symbolic link as long as the target keeps being a symbolic link.
If the final target is a regular file: Source it.
Otherwise: Give it up.
As a test I created a symbolic link ~/.bashrc to the original file .dotfiles/.bashrc. My code enters the elif as intended, but sadly never enters the body of the while-loop (as I would expect, since ~/.bashrc is a symbolic link).
What is going on here? I think the variable assignment of location is wrong in some way.
Replace:
location="$(readlink $path)"
With:
location="$(readlink $location)"
Notes:
The variable path was never defined. I believe that you intended to apply readlink to location instead
If you had GNU readlink (available on Linux, homebrew, etc), then the option -f could be used eliminating the need for a loop.
In general, shell variables should be referenced inside double-quotes unless one wants the shell to apply word splitting, tilde expansion, and pathname expansion to the value of the variable.
For example, in the following line, we want tilde expansion. So, ~/ needs to be outside of quotes:
location=~/.bashrc
Once this is done, the parts of the script where location is referenced should be in double-quotes. As one example:
location="$(readlink "$location")"
This becomes very important, for example, if file or path names contains spaces.
This causes the problem:
location="~/.bashrc"
The tilde expansion doesn't happen in double quotes, and it doesn't happen in
[ -L $location ]
either.
So, don't use double quotes in the assignment, or use
location="$HOME/.bashrc"
or similar.
This command is referenced on this guide: http://mywiki.wooledge.org/DotFiles
# .profile
if [ -n "$BASH" ] && [ -r ~/.bashrc ]; then
. ~/.bashrc
fi
What is the first . on . ~/.bashrc?
Is it referencing my current directory and then home?
"." is equivalent of source in bash.
A dot in this context means to "source" the contents of .bashrc into the current shell
. ~/.bashrc -> source ~/.bashrc
For more details read this: source
Is there a way to execute a command before accessing a remote terminal
When I enter this command:
bash
$> ssh user#server.com 'ls'
The ls command is executed on the remote computer but ssh quits and I cannot continue in my remote session.
Is there a way of keeping the connection? The reason that I am asking this is that I want to create a setup for ssh session without having to modify the remote .bashrc file.
I would force the allocation of a pseudo tty and then run bash after the ls command:
syzdek#host1$ ssh -t host2.example.com 'ls -l /dev/null; bash'
-rwxrwxrwx 1 root other 27 Apr 1 2005 /dev/null
bash-4.1$
You can try using process subsitution on the init file of bash. In the example below, I define a function myfunc:
myfunc () {
echo "Running myfunc"
}
which I transform to a properly-escaped one-liner echoed in the <(...) construct for process subsitution for the --init-file argument of bash:
$ ssh -t localhost 'bash --init-file <( echo "myfunc() { echo \"Running myfunc\" ; }" ) '
Password:
bash-3.2$ myfunc
Running myfunc
bash-3.2$ exit
Note that once connected, my .bashrc is not sourced but myfunc is defined and properly usable in an interactive session.
It might prove a little difficult for more complex bash functions, but it works.
I have two servers A and B, I have a shell script in serverA which logs into serverB (through ssh) and runs the following command:
sh cassandra-cli -h <serverB> -v -f database_import.txt;
so when I do this manually, I follow these steps:
serverA:~$ ssh serverB
serverB:~$ sh cassandra-cli -h <serverB> -v -f database_import.txt;
It works properly when I follow these steps manually but when I automate this process in a shell script by this following line:
serverA:~$ssh serverB "sh cassandra-cli -h <serverB> -v -f database_import.txt;"
I get this error,
cassandra-cli: 46: cassandra-cli: -ea: not found
So, as you already pointed out, $JAVA is empty through ssh.
This is because .bashrc is not sourced when you log in using ssh. You can source it like this:
. ~/.bashrc
And your command is going to look like this:
ssh serverB ". ~/.bashrc; sh cassandra-cli -h <serverB> -v -f database_import.txt;"
You can also try placing this into your .bash_profile instead of invoking it manually each time.
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi