SchoofsKelvin / vscode-sshfs

Extension for Visual Studio Code: File system provider using SSH
GNU General Public License v3.0
543 stars 36 forks source link

Opening file via commandline on remote? #267

Closed SpanishPear closed 2 years ago

SpanishPear commented 3 years ago

Hi!

I was wondering if there's any way to open a mounted file on the commandline from my ssh-terminal (as opened by the extension)?

Thanks!

SchoofsKelvin commented 3 years ago

It'll take a little bit to implement, but I think this can be done when #253 is (partially) implemented/released.

Basically bind to e.g. /tmp/vscode-sshfs-<random-UUID-or-timestamp>.sock which is remotely forwarded by the extension and listens for commands. A bash alias (or even an overridden $EDITOR variable) could then be added to perform echo "open <filepath>\n" > /tmp/.... Haven't tested it yet, but I imagine this would be a relatively simple way of adding support for this.

jcattley commented 3 years ago

The only caveat I'd add:

We're trying to migrate our users to SSH-FS away from remote-ssh, because we have thousands of users connecting to our servers, and the .vscode-server backend that remote-ssh uses is a massive CPU/RAM/pid/disk hog - trivial for single-user boxes, but a major problem for significantly-multi-user environments. (it's also hilariously insecure by default, and people can end up running other users' shells accidentally unless they drill down into the config to use sockets instead of TCP...)

Killing stuck or leftover backend processes by the hundreds, and fielding multiple tickets daily to clear out corrupted or quota-eating .vscode-server directories is also a significant chunk of our daily workflow that we really want to get away from, and if we end up going back there, I may possibly cry.

If you do implement a backend process, I beg you to focus on keeping it as lightweight and stateless as possible. I will owe you one, seriously.

SchoofsKelvin commented 3 years ago

If you do implement a backend process, I beg you to focus on keeping it as lightweight and stateless as possible. I will owe you one, seriously.

I wasn't really thinking about a backend process anyway, as this would require the host to have NodeJS to run the backend code. That, or me having to write and provide (built) executables for every OS, which I'm even less a fan of. My idea was just to have a simple socket (a UNIX one, to prevent having to deal with reserved ports and such) which is either port forwarded through SSH, or optionally running a background SSH terminal that creates and listens to this socket, although the latter is unlikely.

SchoofsKelvin commented 3 years ago

Made some progress, although actually injecting the code alias/function in the shell is tricky. And actually creating a code program in some .../bin directory seems a bit icky.

Currently I'm overwriting the PROMPT_COMMAND environment variable (for Bash) and the ENV environment variable (for sh) to have them load a temporary file (including in subshells) that adds the alias. Not the cleanest, and definitely not the most reliable/robust, let alone whether it supports other shells.

It's either that, going through all possible .profile and similar files and injecting source /tmp/something if not present yet, or having the user manually add that to their profile. and that's assuming I can write a .sh script that all shells accept.

Besides the "how to load code command", I'm not still entirely sure how to actually make it work:

Both issues are already quite complex on their own, so it's taking quite some time and effort to get it working consistently across multiple shells. And I've only tried (and perhaps might even only try) bash and sh, nothing else. I'm assuming that any script I write that's compatible with the Bourne shell (sh) will be source-able by all shells, and that the PROXY_COMMAND/ENV "hack" I'm using now is also good enough.

TL;DR: Lots of work with complex Unix/shell mechanics, but there's at least progress.

I'll probably quickly finish the current half-baked setup I have and push it to a feature branch (or publicly released but only enabled with certain flags), so you can try the code command out yourself and give feedback or, more likely, find bugs. Then I'll continue on #252 before coming back to this.

SchoofsKelvin commented 3 years ago

I've pushed an initial prototype to the master branch, you can download the extension from the latest build in this list.

To activate this feature, there are two ways:

Once that's added, every new connection will make use of the feature, so I recommend reloading the window. When you open a remote terminal through the extension, it should display Injected 'code' alias once and whenever you create an interactive subshell.

The code command expects a single argument, namely a relative or absolute path to a file/directory you want to open. Files will be opened in editors, while directories will be added as workspace folders.

Like I mentioned in my previous comment, the current setup isn't the most elegant or robust, your mileage might vary. Also note that the code command only sends an instruction to the extension and immediately returns. Errors are displayed in VS Code, and the command doesn't wait for the opened editor to be closed. Can't use it for e.g. git for now.

SchoofsKelvin commented 3 years ago

The initial prototype is available in v1.21.0 of the extension, so you don't require to manually download and install the built .vsix file. Nothing changed since my last comment though, e.g. it requires the REMOTE_COMMANDS flag and might easily break.

SpanishPear commented 3 years ago

Thanks heaps @SchoofsKelvin - this looks awesome! I'll have a play around :partying_face:

abiramen commented 2 years ago

Hi @SchoofsKelvin, this seems to be working wonderfully!

That being said, I was wondering if it'd be possible for the code alias to create a file and open it rather than throw an EntryNotFound error if the file doesn't exist

Thanks 😄

SchoofsKelvin commented 2 years ago

@abiramen Can you test the latest build (68 or later) from here? Run the Extensions: Install from VSIX command and select the .vsix artifact file. When trying to open a file that doesn't exist, it should prompt you to create an empty file first.

Mind that it does actually create that empty file. The extension API doesn't seem to allow me to (easily) create an unsaved document for a non-existing URI. Technically I could trick VS Code into allowing this, but hacky and a bit of work.

abiramen commented 2 years ago

This works great! Thanks @SchoofsKelvin 🎉

abaj8494 commented 2 years ago

Would it be possible to add this functionality for the zsh shell also? If not, perhaps a nudge in the right direction so I can try reverse engineer the work done on the sh and bash shells.

So far the profile config files haven't really helped in deciphering how this works.

SchoofsKelvin commented 2 years ago

I've just pushed some commits that should, if I didn't do anything wrong, support most shells. Below is the current list, which I didn't test in-depth yet, but should work for those shells and most shells based on them:

https://github.com/SchoofsKelvin/vscode-sshfs/blob/06a397e5868df5741e895d32ab0726475128e323/src/shellConfig.ts#L74-L83

You can get the latest build from here (build 87 or later) if you want to try it out yourself. I'll release it after some more feedback/testing.

SchoofsKelvin commented 2 years ago

More shell support (from my previous comment) added in v1.24.0 of the extension.

telecasterer commented 2 years ago

Hello,

I'm trying to use this on systems where the default shell is /bin/csh, but it doesn't work. It appears that the shell type is not being detected correctly because the extension tries to use the "export" command to set things up instead of "setenv".

EDIT: I switched on logging but I don't see any errors in the SSH FS log.

example terminal output:

Connecting to eda... export: Command not found. export: Command not found. $

So, check the SHELL value...

$ echo $SHELL /bin/csh

this is actually a link to tcsh:

/bin/csh -> tcsh

Thanks

SchoofsKelvin commented 2 years ago

This issue would be easier to solve with debug logs, so please follow these steps:

That should log which kind of shell it actually thinks you're using. My guess is the detection goes wrong, since csh should get detected: https://github.com/SchoofsKelvin/vscode-sshfs/blob/2673c726c84a3f73983b344ae6c9ce73d8fb284b/src/shellConfig.ts#L82

telecasterer commented 2 years ago

Thanks for the response, here's the log

debug_sshfs.log

I've just noticed that as you suspected there is an error when detecting the shell config :

[ERROR] [createConnection(eda,config)] Error calculating ShellConfig: Error: Command 'echo :::SHELL:$SHELL:SHELL:::' failed with exit code 1: Bad : modifier in $ (S). Error: Command 'echo :::SHELL:$SHELL:SHELL:::' failed with exit code 1: Bad : modifier in $ (S).

I guess this needs to be changed by adding braces:

echo :::SHELL:${SHELL}:SHELL:::

which for csh at least should return: :::SHELL:/bin/csh:SHELL:::

UPDATE: I can confirm that changing $SHELL to ${SHELL} fixes the issue for csh and doesn't cause problems for bash/sh. I've simply updated the minified extension.js file that I already have installed to test this. Would you prefer a pull request?