文章

合租房中建家(二):普通账户复用与VSCode使能

之前的文章中我已经介绍过如果在共用的普通 Linux 账户下配置个人专用的开发环境以尽量避免他人的干扰,这篇文章中将介绍一些更优的做法来进一步改进使用体验。

更好地复用普通账户

此前我介绍了通过在自己的目录中启动新 SHELL 的方式来避免家目录中的 .bashrc 等文件的干扰的方法,但这种方式并不能一定隔绝这些文件的影响,因为 SSH 登录到服务器时总是会先进入 Bash 环境,只要我们的 SHELL 是 Bash 间接启动的,那就难免会受到 Bash 启动文件的影响。

如果账户从一开始就被确定为共用账户,那么我们可以在一开始就将这些文件的影响最小化。

首先,删除 ~/.bashrc~/.bash_profile~/.bash_login ,然后修改或创建 ~/.profile 文件为以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
if [ "$LC_WHO" == "gyh" ]; then
  # 将家目录设置到我自己的目录
  export HOME=$HOME/gyh
  # 直接进入到我自己的 SHELL
  exec ~/path/to/my/zsh
  # exec 可以让 Bash 直接运行后面的程序,而不是启动一个子进程等待它结束,因此该行命令不会返回。
  return
fi

cat <<- EOF
==================== !!! 注意 !!! ====================
==================== !!! 注意 !!! ====================
==================== !!! 注意 !!! ====================

为了尽量消除因共用普通账户而给大家带来的干扰,请所有人遵守以下使用规则:

1. 请在 ~ 中以自己姓名创建独立目录,并将自己的所有文件都放入其中

2. .bashrc 已禁用,请不要在 ~ 中创建 .bashrc .bash_profile
   .bash_login 等文件,更不要在里面写入只适用于自己的配置内容

3. 如果你仍然需要 .bashrc 等环境初始化机制,请考虑通过在自己的目录
   中启动新的 SHELL 来替代实现

   例如: HOME=\$HOME/gyh /bin/bash

4. 你可以通过修改 ~/.profile 来在使用 SSH 连接到服务器时直接使用
   自己的家目录和 SHELL

   请在你的 ~/.ssh/config 中设置 "SetEnv LC_WHO=xxx",然后参考
   ~/.profile 中的既有内容,在其中添加你自己的情况处理代码

5. 千万不要删除别人的目录!
   千万不要删除别人的目录!
   千万不要删除别人的目录!
   (如果你不想被打的话)
EOF

if ! [[ -z "$LC_WHO" ]]; then
  echo "警告:未处理 LC_WHO=$LC_WHO ,请在 ~/.profile 中添加相关的处理代码"
fi

这样,所有人在登录时都会看到这个提示。

然后,修改自己的 ~/.ssh/config 文件,在服务器的配置中添加 SetEnv LC_WHO=gyh

1
2
3
Host PublicServer
   User PublicUser
   SetEnv LC_WHO=gyh

这样在登录时:

  1. SSH 客户端会将 LC_WHO=gyh 环境变量传递给 SSH 服务器;
  2. 服务器会先设置 LC_WHO 环境变量,然后启动 SHELL(即 Bash);
  3. Bash 查找并执行启动文件,最终会运行 ~/.profile
  4. ~/.profile 中检查了 LC_WHO 环境变量,命中了 gyh if 分支;
  5. if 分支里将 HOME 设为自己的目录,然后使用 exec 进入新 SHELL;
  6. 由于 exec 会将原来的 Bash 进程会被替换掉,最终就实现了直接登入自己 SHELL 的效果。

使用这种方式能实现非常好的复用效果,它的实际体验几乎就和拥有一个独立的普通账户一样。

但是这一方式有好几个约束:

  1. OpenSSH 从 7.8 版本才开始支持 SetEnv ,你的客户端和服务器都必须比这更新;
  2. 服务器上的 /etc/sshd_configAcceptEnv 选项里必须允许 LC_WHO 环境变量。

一般情况下(比如 ubuntu22.04 里),sshd 的 AcceptEnv 默认会被设为 LANG LC_* ,因此可以传递这个变量。但是有些安全性比较严格的发行版,比如 RHEL,严格限定了 AcceptEnv 的内容,这时你就需要在服务器上修改 /etc/sshd_config 了。

确切来说,我们这里只是需要一种在 ~/.profile 中识别 SSH 客户端的办法,除了 SetEnv 还可以有其它方式:

  1. 通过 SSH 客户端的 IP 地址来识别,即环境变量 $SSH_CONNECTION

    $SSH_CONNECTION 在很早的 OpenSSH 版本中就已经存在了,因此这种方式适用性最好。但因为 IP 地址很可能不固定,所以这种方式并不是很好的选择。

  2. 通过 $SSH_USER_AUTH 来获取登录所使用的公钥,然后根据公钥来区分不同用户;

    这种方式要求每个用户都用自己的私钥登入这个公共账户,而不是大家一起用一个私钥,这稍微有点麻烦,但问题不大。可是这种方式也需要在服务器上修改 /etc/sshd_config 配置 AuthorizedKeysCommand yes,这个配置项在一些发行版上默认是关闭的。

直白来讲,我私以为最好的方式还是为每个用户分配一个普通账户,就像 Unix 最初被设计的那样。对于系统管理员而言,如果需要管理和计费,则应该改用 Unix 用户组来管理,而不是以账户作为管理单元(毕竟用户组设计出来不就是来干这个事的吗?!),普通用户应该被允许创建同组下的其它用户(这可以通过给定制的 adduser 命令添加 -s 选项来实现),如果有必要,可以设个小组长等等。

使能 VSCode 远程开发

TODO

本文由作者按照 CC BY 4.0 进行授权