kornaque · 2022-12-20 13:28
Hi,
I would like to run and get the result of a command on a remote host with SSH connection, after having activated a virtual env.
In a terminal, I usually do
local $ ssh remote
remote $ source venv/bin/activate
remote (venv) $ midi2wav.py file-on-remote-host.mid
How can I do the same in Emacs, with a single command? Ideally, I would like to get the output of the commands as well.
After reading the documentation of TRAMP, I decided that `start-file-process` or `shell-command` would be the functions I need. I tried this.
(let ((default-directory "/sshx:remote:~/"))
(start-file-process
"tramp-remote"
(get-buffer-create "*Tramp remote process*")
"/bin/bash" "-c" "source ~/venv/bin/activate ; midi2wav.py file-on-remote-host.mid"))
But nothing appears in the buffer "*Tramp remote process*". There are many other commands for running a program in Emacs, like `call-process`, `process-file`, etc, but I am a bit lost in which can be used here.
Thanks for help!
JDRiverRun · 2022-12-20 18:57
A good trick for "activating" a venv temporarily without all the bother is to just call the python executable it stores, so something like: `/venv/bin/python midi2wav.py file-on-remote-host.midi`.
So (noting you can't use `~` bare like that):
(let ((default-directory (expand-file-name "/ssh:remote:~/my/venv")))
(shell-command-to-string "bin/python3 -V"))
astoff1 · 2022-12-21 07:48
To complement this a bit, the permanent way to do it is to set the variable `tramp-remote-path`. You can use a connection-local variable if you use multiple Tramp remotes.
kornaque · 2022-12-22 11:18
Awesome! Thank you!
I did not know that all `source venv/bin/activate` was doing was just setting the `PATH` variable. So directly getting to the `bin/` folder does the trick.
EDIT: I solved my second question concerning setting the shell, thanks to connection-locale variables, thanks guys! :)
Second question: Is there any way to choose in which shell the command will be executed?
Solution: Use connection-local variable to set the shell to /bin/fish, for example.
```
(connection-local-set-profile-variables
'remote-fish
'((shell-file-name . "/bin/fish")
(shell-command-switch . "-c")
(shell-interactive-switch . "-i")
(shell-login-switch . "-l")))
(connection-local-set-profiles
'(:application tramp :protocol "ssh" :machine "myremote")
'remote-fish)
(let ((default-directory (expand-file-name "/ssh:myremote:~/")))
(with-connection-local-variables
(shell-command-to-string "foobar")
))
```
Now, if fish is installed on the remote, it should run as the shell!