为什么在 Linux 自托管 运行ner 上的 Github 操作需要用户交换每个命令,如果你不想 运行 在 root 上

Why does a Github Action on a Linux self-hosted runner require a user swap for every command if you dont want to run on root

我编写了一个工作流程,用于在 Linux 自托管 GitHub 运行ner VM 上安装一些工具依赖项。我正在使用自制软件来安装工具。使用 homebrew 要求它不是 运行 root 用户,这是 GitHub Runner 登录的用户。我想知道为什么当我创建一个将用户从 root 切换到我的测试用户的步骤时,事情会中断,但是当我在每个步骤中对该用户执行 sudo 时,一切正常,我想我解释得不好所以见下文:

失败的工作流程(您可以看到第一步将用户切换为 testUser):

 installHomebrew:
    name: Install Homebrew
    runs-on: [self-hosted]
        
    steps:
      - name: Switch to etpAdmin user
        run: sudo -u testUser -i

      - name: Install Homebrew silently
        run: sudo apt install linuxbrew-wrapper -y
        
      - name: Run brew for the first time to create the .linuxbrew directory
        run: brew -h

这将在最后一步失败,声称自制软件不应该 运行 在 root 上,而以下工作流程工作正常。

 installHomebrew:
    name: Install Homebrew
    runs-on: [self-hosted]
        
    steps:
      - name: Install Homebrew silently
        run: sudo apt install linuxbrew-wrapper -y
        
      - name: Run brew for the first time to create the .linuxbrew directory
        run: sudo -u testUser -i brew -h

我的 Linux 有点生疏,但我的印象是使用 sudo -u (username) -i 将终端登录到指定的用户,直到再次成为 logout/switching 用户,我错了吗?更好的方法来完成这个?

免责声明;我不熟悉您 运行 正在使用的平台或您正在使用的工具,但我确实有一个有根据的猜测..我希望这也是 -i 标志的行为方式。

由于大多数供应商的工作,他们通常 运行 每个步骤(大部分)独立于其他步骤。这(同样,通常)意味着一个步骤的环境不会转移到下一个步骤。所以在这种情况下,一步运行宁sudo -i不会对后面的步骤有任何影响。您可以试试这个,看看您的案例中的供应商是如何运作的:

testUserChange:
    name: Test active user
    runs-on: [self-hosted]
        
    steps:
      - name: Default user
        run: whoami
        
      - name: Sudo user
        run: sudo -u testUser -i whoami

      - name: Should be default user again
        run: whoami

      - name: Maybe interactive shell like in first attempt
        run: sudo -u testUser -i

      - name: Who am I now
        run: whoami

现在关于 -i,手册指出:

This means that login-specific resource files such as .profile or .login will be read by the shell. If a command is specified, it is passed to the shell for execution via the shell's -c option. If no command is specified, an interactive shell is executed.

虽然这可能有点令人困惑,因为大多数供应商不希望用户在 运行 时进行交互输入,但他们通常会关闭 STDIN 句柄(进程的输入)。如果我们有两个用户,user0neusertw0,我希望我能演示该行为;

$ export PS1="This is user0ne env $ " # just to show when environment variables are re-set due to loading the login scripts
This is user0ne env $
This is user0ne env $ whoami
user0ne
This is user0ne env $ sudo -u usertw0 /bin/sh
This is user0ne env $ whoami
usertw0
This is user0ne env $ exit
This is user0ne env $ whoami
user0ne
This is user0ne env $

在上面的例子中,你可以看到当有效用户是tw0时,环境仍然设置为0ne所设置的。让我们试试 -i:

This is user0ne env $ sudo -u usertw0 -i /bin/sh
$ whoami
usertw0
$ exit
This is user0ne env $

所以现在,看起来 -i 将环境(和登录)设置为 tw0。现在,虽然文档确实声明没有任何参数,但交互式 shell 已打开:

This is user0ne env $ sudo -u usertw0 -i
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

usertw0@ubuntu:~$ logout
This is user0ne env $

让我们看看如果我们关闭输入处理程序(或者更准确地说,什么都不输入)会发生什么:

This is user0ne env $ sudo -u usertw0 -i < /dev/null
This is user0ne env $ whoami
user0ne
This is user0ne env $

即使您提供 /bin/sh 作为 运行 的命令,也会发生同样的情况,如上面的代码片段所示:

This is user0ne env $ sudo -u usertw0 -i /bin/sh < /dev/null
This is user0ne env $ whoami
user0ne
This is user0ne env $

所以即使文档确实声明它会打开一个交互式 shell,一旦没有要读取的输入,shell 就会关闭,状态 returns 到上一个用户。

干杯! :)