tramp 连接ubuntu远程开发时环境变量怎么设置

主机 win10,虚拟机 ubuntu20.4,用plink能成功连接并运行 python 代码,但环境变量(PATH,PYTHONPATH)不对。应该是没有 source ~/.bashrc。/etc/profile, /etc/bash.bashrc 都设置了,不起作用。有没有哪位大佬指导下怎么设置。

在手册上找到种方法,手工设置环境变量暂时解决了。

(add-to-list 'tramp-remote-process-environment "JAVA_HOME=/opt/java")

但手册中提到的设置 (setenv “ENV” “$HOME/.profile”) 的方法不起作用。

经大佬提醒,手册中完整的是:

Setting the ENV environment variable instructs some shells to read an initialization file. By default, TRAMP disables this. You can override this behavior by evaluating

(let ((process-environment tramp-remote-process-environment))
  (setenv "ENV" "$HOME/.profile")
  (setq tramp-remote-process-environment process-environment))

引用代码的时候应该严谨一些。你这么写,我可能会认为:

  1. 你在代码里把引号写错了。
  2. 你这句代码放的位置不对。

谢谢提醒,已经修改。

看了下 bash 的参数有 -norc -noprofile。但去掉 -norc后连不上,原因未知。

怎么认定「不起作用」?你用什么方法/步骤观察?

$ emacs -Q  --eval '
  (let ((default-directory "/ssh:user@host:"))
    (message "==> %s" (shell-command-to-string "echo $VAR_IN_PROFILE")))' --batch
Tramp: Sending command ‘exec ssh -o ControlMaster=auto -o ControlPath=tramp.%C -o ControlPersist=no -e none user@host’
Tramp: Found remote shell prompt on ‘user@host’
==> Value of VAR_IN_PROFILE

我是在python中直接打印环境变量发现的:

import os
print(os.environ["PATH"])
print(os.environ["ENV"])
print(os.environ["TERM"])
print(os.environ["PYTHONPATH"])

输出:

-*- mode: compilation; default-directory: "/plink:hadoop@ubuntu:~/test/" -*-
Compilation started at Wed Mar 29 14:23:04

python3 a.py
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
~/.profile
dumb
Traceback (most recent call last):
  File "a.py", line 7, in <module>
    print(os.environ["PYTHONPATH"])
  File "/usr/lib/python3.8/os.py", line 675, in __getitem__
    raise KeyError(key) from None
KeyError: 'PYTHONPATH'

Compilation exited abnormally with code 1 at Wed Mar 29 14:23:04

~/.profile 中设置了环境变量了,服务器上输出(ENV,没设,服务器上注释掉了):

hadoop@hh:~/test$ python3 a.py
/usr/lib/jvm/java-11-openjdk-amd64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/spark/hadoop/sbin:/opt/spark/hadoop/bin:/opt/spark/hadoop/sbin:/opt/spark/hadoop/bin
xterm
/opt/spark/spark/python/lib/py4j-0.10.9.5-src.zip:/opt/spark/spark/python/lib/pyspark.zip:/opt/spark/spark/python/lib/py4j-0.10.9.5-src.zip:/opt/spark/spark/python/lib/pyspark.zip:/opt/spark/spark/python/lib/py4j-0.10.9.5-src.zip:/opt/spark/spark/python/lib/pyspark.zip:/opt/spark/spark/python/lib/py4j-0.10.9.5-src.zip:/opt/spark/spark/python/lib/pyspark.zip:

emacs -Q 下 PATH环境环境变量也不对。

你试运行一下我前面提供的脚本。


确认一下远程主机的 profile 启动顺序,各个系统有差别。有的可能不执行 .profile,换 .bash_profile.bashrc 试试。

大佬,运行不了,我才手动用 Emacs -Q的, 就是上面那个截图。启动后没做别的,就只把 plink 加进emacs 的 path,然后才能用 tramp plink 连接 linux。

运行你给的脚本有个概念没搞懂,怎么输入密码?放 .netrc 文件似乎不行。

  1. 在 msys 下运行:
$ emacs -Q  --eval '(let ((default-directory "/ssh:[email protected]:")) (message "==> %s" (shell-command-to-string "echo $PATH")))' --batch
Tramp: Sending command `ssh -l hadoop -e none 192.168.43.172 && exit || exit'
File error: Tramp failed to connect.  If this happens repeatedly, try
    `M-x tramp-cleanup-this-connection'
Tramp failed to connect.  If this happens repeatedly, try
    `M-x tramp-cleanup-this-connection'

lld@Win10-2022HSFQW MINGW64 ~
$
  1. 在windows命令行下运行:
C:\Users\lld>emacs -Q  --eval '(let ((default-directory "/plink:[email protected]:")) (message "==> %s" (shell-command-to-string "echo $PATH")))' --batch

Error: end-of-file nil
  debug-early-backtrace()
  debug-early(error (end-of-file))
  command-line-1(("--eval" "'(let" "((default-directory" "/plink:[email protected]:))" "(message" "==> %s" "(shell-command-to-string" "echo $PATH)))'"))
  command-line()
  normal-top-level()
End of file during parsing

如果你在 ~/.ssh/config 设置了 IdentityFile,就可以免密。如果没有设置,就会询问密码:

$ emacs -Q --eval '
   (with-current-buffer (find-file-noselect "/ssh:[email protected]:~/.profile")
       (message "==> %S" (shell-command-to-string "echo $loaded")))' --batch
Tramp: Sending command ‘exec ssh -l root -o ControlMaster=auto -o ControlPath=tramp.%C -o ControlPersist=no -e none 192.168.1.1’
Tramp: Sending password
Password for /ssh:[email protected]: ▋
(connection-local-set-profile-variables
 'remote-bash
 '((explicit-shell-file-name . "/bin/bash")
   (explicit-bash-args . ("-i"))
   ))

(connection-local-set-profiles
 '(:application tramp :protocol "plink" :user "xxxx" :machine "xxxx")
 'remote-bash)

免密登录在 gui 可以了,但在 batch 下不行。

谢谢两位。如图,环境变量仍然不对。

是否免密不是重点。

你的问题是环境变量没有生效。如我前面所说,你应该看看远程主机是什么系统和shell,是加载 .bash_profile 还是 .profile。如果 tramp 登录有问题,ssh 直接登录应该也有问题:

找到了解决办法,加载的是 .bashrc 文件。

要点1:将 tramp-own-remote-path 加进 tramp-remote-path

要点2:覆盖默认的 命令行参数,用 (explicit-bash-args . ("-i"))

(with-eval-after-load 'tramp
  (add-to-list 'tramp-connection-properties
               (list (regexp-quote "/plink")
    				 "remote-shell" "/bin/bash"))
  (connection-local-set-profile-variables
   'remote-bash
   '((explicit-shell-file-name . "/bin/bash")
     (explicit-bash-args . ("-i"))
     ))
  (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
1 个赞

补充一下,执行完后记得 tramp-cleanup-all-connections 然后再试一下 (executable-find "your-program" t) 试试看能不能找到远端的应用程序。

我觉得 tramp-remote-path 真该默认包含 tramp-own-remote-path :smiling_face_with_tear:

我也觉得应该包含。通过 tramp-remote-process-environment 的方式用了好久。

(add-to-list 'tramp-remote-process-environment
			   (format "PYTHONPATH=%s" (getenv "PYTHONPATH_REMOTE")))