Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable custom shell initialization script on the remote #141

Open
davidwin opened this issue May 5, 2019 · 47 comments
Open

Enable custom shell initialization script on the remote #141

davidwin opened this issue May 5, 2019 · 47 comments
Assignees
Labels
feature-request Request for new features or functionality plan-review PM-highlighted item determined to be P1 or P2 ssh Issue in vscode-remote SSH
Milestone

Comments

@davidwin
Copy link

davidwin commented May 5, 2019

The system where I would use the Remote SSH feature has a quite "vintage" tool setup by default, which causes installation of the extension to fail. By modifying my .bashrc I am able to work around this with generous use of module add, but now my whole environment is "non-standard", and build tools ding me for this, even if I'm not using Code. I'm sure that at some point I will spend days looking for a bug caused by me swapping out the core GNU tooling for a different version.

I suggest adding the possibility to specify a script that is sourced on the remote before executing the installation and launching the extension server. It doesn't have to be a setting, just a script with a known name. This would put the remote tools on equal footing with the IDE itself, where i am able to run code inside a custom environment by sourcing a setup script first, without having to "pollute" my .bashrc.

This request might be slightly related to #83.

@egamma egamma added ssh Issue in vscode-remote SSH feature-request Request for new features or functionality labels May 5, 2019
@kieferrm kieferrm added this to the May 2019 milestone May 5, 2019
@juanrh
Copy link

juanrh commented May 14, 2019

This might also be useful for ROS development, as running source on a setup.bash file` is part of the basic development cycle

@roblourens roblourens self-assigned this Jun 3, 2019
@roblourens
Copy link
Member

Can you explain some more about what you are looking for? Is this about running the rc file for some non-bash shell? If so that should work now. Or running a custom arbitrary script which would not normally be run for an ssh session?

@roblourens roblourens removed this from the May 2019 milestone Jun 3, 2019
@juanrh
Copy link

juanrh commented Jun 4, 2019

It would be more the second thing, "running a custom arbitrary script which would not normally be run for an ssh session".

In ROS there is this concept of workspace overlay that is used to extend the set of ROS packages available at build time and at runtime. The base workspace corresponds to your ROS installation, usually in /opt/ros/${ROS_DISTRO} (e.g. /opt/ros/kinetic), and is activated by running source /opt/ros/${ROS_DISTRO}/setup.bash. That source command can be added to ~/.bashrc, but often it isn't because you can have different ROS distributions installed in your workstation, and use that source command to activate the different distros. This is because often ROS packages are supported in several distributions (see e.g. https://index.ros.org/p/ros2launch/), and having several ROS distros installed is useful for development.

But even if you only have a single ROS distribution installed in your workstation, you'll probably have several ROS workspaces. A ROS workspace is a project folder where you develop several ROS packages. There is a standard directory layout in a workspace, where a src directory contains the code, a build directory contains the temporary files for CMake builds, and an install directory contains the installed binaries. The src directory contains the source code for several ROS packages, that are directories with a file package.xml and also different files depending on the language used to implement the package, which is usually either Python or C++ (based on CMake). You have to run source install/setup.bash to add the artifacts in your local workspace to the scope for building and running. That source command "overlays" the local workspace on top of the base workspace that corresponds to the active ROS distro. So a typical development workflow in ROS is something as follows:

cd ~/myworkspace
# activate a ROS distro
source /opt/ros/kinetic/setup.bash
# run build commands: this creates the `install` directory 
colcon build 
# run unit tests
colcon test 
# activate local workspace
source install/setup.bash
# launch a program "bar" installed in the package "foo"
roslaunch foo bar

When I have used vscode to develop C++ packages in ROS, which are based on CMake, I usually do source /opt/ros/kinetic/setup.bash && colcon build && source install/setup.bash and then I launch vscode, and use the extension CMake Tools on a specific C++ ROS package in the workspace. But if I skip source install/setup.bash or launch vscode without the env vars defined by that source, then the plugin doesn't work, because that source is configuring several env vars that are expected by the CMake scripts used by the ROS build system (see e.g. https://github.com/ros/catkin/tree/kinetic-devel/cmake), and that are used to switch between workspaces.

@davidwin
Copy link
Author

davidwin commented Jun 4, 2019

@juanrh describes the situation very well. The key issue is that when running Code in the traditional local mode, you always have the option of launching it from a shell where you've prepared the environment for the various plugins, but this possibility is lost in remote mode. (In my case, the installer won't even run unless I modify my .bashrc to swap out the GNU tooling.)

The only workaround that I can think of, modifying my .bashrc for developing a specific project, is bound to cause problems and makes it impossible to open two projects in parallel.

@roblourens
Copy link
Member

Ok, thanks I think I understand. I will have to think about this. One solution could be an extension that runs the script on startup and modifies the extension host environment.

@davidwin
Copy link
Author

davidwin commented Jun 4, 2019

Would an extension be capable of modifying the environment required to install the extension host in the first place? Does it have to be an extension instead of a step in the launch script for the extension host (assuming that it is a sh script in the first place)?
Thanks for giving this some thought!

@roblourens
Copy link
Member

An extension can only modify the extension host's environment after it is already running, which may or may not work for whatever CMake Tools is doing.

@davidwin
Copy link
Author

davidwin commented Jun 4, 2019

If the environment is specified by a shell script, would the extension realistically be able to modify the environment of the running Node process short of coming up with some in-process sh interpreter? (I'm sorry if I have misunderstood how the extension would operate.)

@roblourens
Copy link
Member

process.env can be modified, and this would be the same environment that other extensions see. The extension would have to figure out how the shell script modified the environment, probably you would have to modify the shell script to write output that the extension can parse. For example it can write

FOO=bar

and the extension can read that and write process.env['FOO'] = 'bar'.

It can even invoke node to JSON.stringify the environment, read that output, parse it, and copy it into the extension hosts' process.env. We do something that like that here:

https://github.com/microsoft/vscode/blob/20ec76e47b427507141565aa75a0a599e9539d1d/src/vs/code/node/shellEnv.ts#L28

But yeah this would take some extra effort to set up but it might be something that can unblock you.

It's hard to think about how this would work as a builtin feature because we avoid features that tell vscode to run an arbitrary script just by opening a folder. Like if this existed, it would be disabled by default and something that you have to clearly opt in to per-workspace.

@roblourens
Copy link
Member

Oh and another solution, we should get this to work if you

  • open another remote folder, or an empty window on that remote
  • Run the script in the integrated terminal
  • Then run code-insiders <workspace> in the terminal

@Tyriar tldr:
would it make sense, when launching vscode with the remote cli, to have the new remote EH somehow get the environment of the terminal from where it was launched? I think we would have to send the full environment along with the command to launch a new window.

@Tyriar
Copy link
Member

Tyriar commented Jun 7, 2019

@roblourens there are issues around this in the vscode repo:

I don't think the remote stuff should differ from local until microsoft/vscode#15452 is actioned.

@roblourens
Copy link
Member

roblourens commented Jun 7, 2019

Oh ok. 15452 makes sense but then I don't know how it will work for the use case above. Probably the extension just needs to set up its environment for itself.

@davidwin
Copy link
Author

I wouldn't mind a solution that required some manual step to have the proper initialization run, because this is already the case when I "source my dev environment" before launching the IDE. However, if it involves modifying the environment after the server has launched, it won't work. For instance, after successfully getting a large corporation to change their SSH security settings to allow VS Code port forwarding (I can tell you the remote extension is making waves here), I'm now stuck because of #103. I need a newer GLIBCXX, but modifying LD_LIBRARY_PATH in my .bashrc is a non-starter. Also, I'm fairly certain the failure happens so early that an extension patching up the Node environment wouldn't help.

I understand why you want to avoid running any code automatically by simply opening a folder, so this shouldn't simply be a workspace setting. Would it be possible to pass options from the local Code instance to the server? Or, could the SSH session used to launch the server optionally be started in interactive mode attached to a terminal, so I can do whatever setup is needed and then launch the server process by running code from there?

@MBetters
Copy link

MBetters commented Jul 1, 2019

FYI for anyone trying to use the CMake Tools extension within a window spawned from this extension, there's an open feature request to allow CMake Tools to source a setup script before running.

@MBetters
Copy link

MBetters commented Jul 1, 2019

I made a workaround script. Use at your own risk.

@anton-malakhov
Copy link

+1 My use case is to enable conda's (or other package or container management) build environment for a vscode project

@MikeZhu92
Copy link

MikeZhu92 commented Nov 7, 2019

+1 must have feature for ssh-remote to work with ROS

Right now default build won't work since for some reason catkin_make showing "no such file or directory"

@roblourens roblourens added this to the November 2019 milestone Nov 11, 2019
@valerioformato
Copy link

+1 also in high energy physics the most common workflow would be to delegate the environment setup to a single bash script, and this issue is a blocker for remote working with vscode

@roblourens
Copy link
Member

To be clear, you can still use .bashrc or .profile or whatever you would normally do for your environment. This feature request is for a script to do vscode remote-ssh specific configuration that you don't want in a normal shell on that host.

@idavydov
Copy link

It is also very difficult to use vs code without this feature with clusters, since everything will be running on the login node (see #2808).

@idavydov
Copy link

To be clear, you can still use .bashrc or .profile or whatever you would normally do for your environment. This feature request is for a script to do vscode remote-ssh specific configuration that you don't want in a normal shell on that host.

Yes, but as far as I understand code in .bashrc cannot distinguish between normal interactive run and connection via vs code If the remote extension would set some environment variable, that would already help in majority of the use-cases, I believe.

E.g., using something similar to RemoteCommand VSCODE_REMOTE_SESSION=1 bash (see #158).

@bamurtaugh bamurtaugh added the plan-review PM-highlighted item determined to be P1 or P2 label Nov 20, 2020
@pknowles
Copy link

As a workaround for building I set up my build environment manually in a screen session and have a script that can inject a command (screen -X stuff ...) and retrieve the output for error parsing (via named pipes):

https://stackoverflow.com/a/42032234/1888983

@bpleon
Copy link

bpleon commented Jun 1, 2021

To be clear, you can still use .bashrc or .profile or whatever you would normally do for your environment. This feature request is for a script to do vscode remote-ssh specific configuration that you don't want in a normal shell on that host.

Does it actually honour .profile? I have a source script.sh line in my .profile; this gets executed when I ssh in from Windows Terminal, but not when I go in via VS Code.

Has there been any work-around for this? I need the VSCode remote extension to run as a different to the user that is logged in.

@leon-v
Copy link

leon-v commented Jun 2, 2021

In case it helps anyone else,
This is how I managed to get my VSCode remote backend running as www-data. May work with logging in with password, but I used SSH keys. Should work with other users.
I use Ubuntu 18.04 and 20.04. Only tested on 20.04.

  1. Give www-data a shell and check its home folder.
    NOTE: Giving the www-data user a shell will allow it to run commands if used. This may be a security issue for your enviroment.
$ sudo nano /etc/passwd

Find www-data in the list, at the end of the line for www-data you will see something like /var/www:/usr/sbin/nologin which is in the format HOME_DIR:SHELL.
To allow the www-data user shell access, change the shell to the same value as a normal user, e.g. /bin/bash. You can look at others users in the file to see what they use.
Save the file.

  1. Setup home directory structure for SSH login, use the home directory from above.
$ sudo chown www-data:www-data /var/www
$ sudo mkdir /var/www/.ssh
$ sudo chown www-data:www-data /var/www/.ssh
  1. Setup keys on host and client.
    For this i use PuTTYgen, but there are many resources on how to generate SSH keys.
    Generate a new key in PuTTYgen.
    Get a copy of the OpenSSH RSA public key from the text box. key string starts with "ssh-rsa"
$ sudo nano /var/www/.ssh/authorized_keys

Paste your OpenSSH RSA public on a new line nas save and close.

$ sudo chown www-data:www-data /var/www/.ssh/authorized_keys
$ sudo service ssh restart

And for VSCode:
In PuTTYgen, click Conversions/Export OpenSSH Key and save the private key soemwhere safe.
Also worth saving the ppk by clicking "Save private key" so you can open it again with PuTTYgen if you need to.
Update the VSCode SSH configuration file to have an entry like this:

Host example.com:www-data
  HostName example.com
  User www-data
  IdentityFile C:\Path\To\Private\OpenSSH\Key\File
  1. Now you should be able to SSH into the server as www-data

@pehamraza
Copy link

Worked for me. Thanks @leon-v

@eromoe
Copy link

eromoe commented Sep 7, 2021

Anyway to su another user after ssh ?

@binus
Copy link

binus commented Sep 25, 2021

To be clear, you can still use .bashrc or .profile or whatever you would normally do for your environment. This feature request is for a script to do vscode remote-ssh specific configuration that you don't want in a normal shell on that host.

Yes, but as far as I understand code in .bashrc cannot distinguish between normal interactive run and connection via vs code If the remote extension would set some environment variable, that would already help in majority of the use-cases, I believe.

E.g., using something similar to RemoteCommand VSCODE_REMOTE_SESSION=1 bash (see #158).

Agree. Seems the remote-ssh honors .bashrc (I don't mean the integrated terminal, I mean for the vscode server and other extensions running remotely). If one special environment variable can be set to indicate it is vscode related, then custom script can be invoked from .bashrc, and it seems the simplest way to have a same and good experience as local vscode when working remotely. (locally: source a script to setup any related environment, then load vscode and any spawn extension/toolkit using this same environment. ).

@leon-v
Copy link

leon-v commented Nov 14, 2021

I have been re-visiting this issue lately, and i see no progress in getting the server to run as a different user, even with sudo.
I have tried to use .bashrc and .profile in a few different environments, and it changes nothing.
What i really want is to change the environment that VSCode server is running in, The SSH RemoteCommand option should allow this, but it appears there are limitations with the way SSH is initalised.

Ill be following this thread for updates:
#4474

@tanhakabir
Copy link

RemoteCommand was enabled with the setting remote.SSH.enableRemoteCommand in the pre-release version of the SSH extension. You also need to have remote.SSH.useLocalServer enabled to use RemoteCommand.

Let me know if it solves what you all are looking for?

@daniel-zeng
Copy link

daniel-zeng commented Jan 31, 2022

This option sounds great @tanhakabir ! Unfortunately running into errors using it on Windows 10. I followed @rzhao271 's latest comment here #6221 but the connection ends up crashing / I'm unable to connect. Thanks! Here's the crash log.

@tanhakabir
Copy link

@daniel-zeng from your logs I'm seeing just "Permissions denied" error so I'm assuming there's some issue authenticating? https://gist.github.com/daniel-zeng/74f11926653140f20fd48dd5b0cd892c#file-gistfile1-txt-L15

If you're unsure why you're seeing an authentication error or want to discuss more, could you please create another issue and we can debug there? Thanks!

@SimeonEhrig
Copy link

RemoteCommand was enabled with the setting remote.SSH.enableRemoteCommand in the pre-release version of the SSH extension. You also need to have remote.SSH.useLocalServer enabled to use RemoteCommand.

Let me know if it solves what you all are looking for?

I used this option successful until today. But now, I have a problem, that my remote Linux system is detected as Windows system and remote.SSH.remotePlatform does not solve the problem: #6319

@SimeonEhrig
Copy link

After some trouble with remote.SSH.enableRemoteCommand I found a new approach that seems to be more robust. I create an extra SSH entry to the same system for each environment in the .ssh/config and pass a specific environment variable via SetEnv:

# normal login
Host dev-system
Hostname dev-system
User user
IdentityFile ~/.ssh/dev-system

# special login for vsc for the alpaka project
Host vsc-dev-alpaka
Hostname dev-system
User user
IdentityFile ~/.ssh/dev-system
SetEnv MY_CONDA_ENV=alpaka-dev

# special login for vsc for the vikunja project
Host vsc-dev-vikunja
Hostname dev-system
User user
IdentityFile ~/.ssh/dev-system
SetEnv MY_CONDA_ENV=vikunja-dev

On the dev-system I added following code in the .bashrc:

if [ ${MY_CONDA_ENV:+x} ]; then
    conda activate ${MY_CONDA_ENV}
fi

Caution: The environment variable must be set in the AcceptEnv LANG LC_* line in the /etc/ssh/sshd_config file on the remote system. When a variable is added, a restart of the sshd service is also required (sudo systemctl restart sshd.service).

@phil-blain
Copy link

phil-blain commented Apr 23, 2022

Small trick:

Caution: The environment variable must be set in the AcceptEnv LANG LC_* line in the /etc/ssh/sshd_config file on the remote system. When a variable is added, a restart of the sshd service is also required (sudo systemctl restart sshd.service).

And if you don't have permission to change the sshd config, just hack it: use LC_MY_CONDA_ENV instead since the default SSH config for several OSs is to accept LC_*. Or if it's not the case on your system, you could hack it even more by abusing TERM, which is always accepted (you might need RequestTTY though).

@phil-blain
Copy link

@SimeonEhrig but just to clarify your specific use case (conda), is there any reason why the "Environments" feature of the Python extension does not work for your use case ? It would seem simpler than adding an SSH config for each of your projects...

@SimeonEhrig
Copy link

@SimeonEhrig but just to clarify your specific use case (conda), is there any reason why the "Environments" feature of the Python extension does not work for your use case ? It would seem simpler than adding an SSH config for each of your projects...

Yes, I use the conda environment mainly for C++ development. Therefore the cmake-tools extension needs to use the correct environment and I didn't found a working solution for this, except starting vsc in the correct conda environment.

@vignesh0025
Copy link

Have the same need for my work. I need to source a complex script to setup my environment, specific to the project. When using VSCode remote, I don't have any way to source the script.

@SimeonEhrig
Copy link

I read this blog post in the morning: https://code.visualstudio.com/blogs/2022/07/07/vscode-server
The vsc code server should be decoupled from the desktop client so that it can run in a specific environment.

@rayson-chan
Copy link

For those of you using clusters, the ssh proxying solution may help, though it didn't benefit me in my case, since I am not authorized to connect a specific interactive compute node directly (w/o knowing its local password).

@mgrosvenor
Copy link

mgrosvenor commented Oct 12, 2022

I have this problem as well. When I log into a remote box I often need to run a configuration script to set up the development environment. This involves loading various versions of tools and setting various configuration options. All I need is the ability to run a single arbitrary shell command after the ssh session is connected and operational. The above suggestion to "put it in your .bashrc or .profile files" is not sufficient because for different projects I need to run different scripts (on the same box). I can't have multiple conflicting versions of tools in my environment at the same time.

@inspector71
Copy link

My use case or need is close to this Issue's topic but I'm unsure. Would be great if anyone can help clarify.

Relatively VS Code newbie. Previously used PuTTY for all commands on the remote server (git, file system, psql and more) and a separate text editor that provided simple Ctrl + S to save via SFTP.

On the remote (Ubuntu) server, I customized various configuration files to get bash running the way I like it: git status in the prompt, shortcut aliases and so forth. It was abit messy to set up. Relies on domino effect (or, as some people call it, "the unix philosophy") to do a few different tricks / tweaks. Ran every time I connected to give me a sweet set up that worked for me well.

The separate SFTP-supporting text editor and PuTTY functionality is seemingly all rolled into VS Code (albeit via a local machine installation of OpenSSH?) in one app / window. This is outstandingly helpful and I'm 98% close to the ideal setup.

However, when I open a terminal in VS Code, I get a nicely-enough coloured prompt but basically the configuration files I previously used, to get the environment I like via PuTTY, do not run.

I can run the configuration files manually via source and the VS Code terminal then becomes the exact equivalent of what I had when using PuTTY and a separate text editor. A perfect little dev env for moi!

Happy to provide more details of the "configuration files" I refer to, and what they do, if that helps.

How can I run remote configuration files automatically every time a VS Code ("Remote - SSH" enabled / connected) Terminal is opened / connected to the remote server?

@NicoLugil
Copy link

I have the same requirement. To setup my project specific environment I need to run something like my_command <projectname>. Seems like a trivial addition to provide a per-workspace possibility to run a script at connection?

@SimeonEhrig
Copy link

I have the same requirement. To setup my project specific environment I need to run something like my_command <projectname>. Seems like a trivial addition to provide a per-workspace possibility to run a script at connection?

Per workspace should be much more complicated than per instance. VSC has no built-in environment management, which means ether vsc has to see all application/dependencies at start up or an extension can handle changing dependencies at runtime. For example, the C++ extension can easily detect new compiler on runtime, but if you need another version of a library (e.g. boost), you need to change the library paths and restart vsc.

By the way. Now I use visual studio code server, which allows me easily to start a vsc instance in a specific instance on the remote system. I have only trouble with the limit of 10 registered instance at the same point. We have 3 workstations, so I have can only us about 3 different environment per system without workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for new features or functionality plan-review PM-highlighted item determined to be P1 or P2 ssh Issue in vscode-remote SSH
Projects
None yet
Development

No branches or pull requests