You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins执行sudo脚本报错:需终端读取密码(新手求助)

解决Jenkins使用sudo时出现"sudo: a terminal is required to read the password"错误

问题背景

Jenkins部署在独立服务器,已与GitLab服务器集成,且在GitLab服务器的/etc/sudoers中为jenkins用户配置了sudo权限,但执行Jenkins pipeline时仍报错:sudo: a terminal is required to read the password。

现有配置

Jenkinsfile

pipeline {
    agent {
        label 'gitlab-server'
    }
    tools {
        maven '3.6.3'
    }
    environment {
        appUser = "shoeshop"
        appName = "shoe-ShoppingCart"
        appVersion = "0.0.1-SNAPSHOT"
        appType = "jar"
        processName = "${appName}-${appVersion}.${appType}"
        folderDeploy = "/datas/${appUser}"
        buildScript = "mvn clean install -DskipTests=True"
        copyScript = "echo '123' | sudo -S cp -r target/${processName} ${folderDeploy}"
        permsScript = "sudo chown -R ${appUser}. ${folderDeploy}"
        killScript = "sudo kill -9 \$(ps -ef| grep ${processName} | grep -v grep | awk '{print \$2}')"
        runScript = 'sudo su ${appUser} -c "cd ${folderDeploy}; java -jar ${processName} > nohup.out 2>&1 &"'
    }
    stages {
        stage('build') {
                steps {
                    sh (script: """ ${buildScript} """, label: "build with maven")
                }
        }
                stage('deploy') {
                steps {
                    sh (script: """ ${copyScript} """, label: "copy the .jar file into deploy folder")
                    sh (script: """ ${permsScript} """, label: "set permission folder")
                    sh (script: """ ${killScript} """, label: "terminate the running process")
                    sh (script: """ ${runScript} """, label: "run the project")
                }
        }
    }
}

/etc/sudoers配置

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
jenkins ALL=(ALL) NOPASSWD: /bin/cp*
jenkins ALL=(ALL) NOPASSWD: /bin/kill*
jenkins ALL=(ALL) NOPASSWD: /bin/chown*
jenkins ALL=(ALL) NOPASSWD: /bin/su shoeshop*
# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers

错误原因

  1. sudoers命令匹配规则错误:配置中的/bin/cp*、/bin/su shoeshop*等写法不符合sudo的匹配逻辑,sudo不会将*作为通配符匹配参数,导致实际执行的命令未被纳入NOPASSWD权限范围。
  2. Jenkinsfile中命令冗余/写法错误:
    • 已配置NOPASSWD仍使用echo '123' | sudo -S传递密码,反而可能触发终端检测;
    • runScript使用单引号包裹,导致变量${appUser}等无法被正确解析;
    • sudo su的写法需要终端交互,且不如直接用sudo -u更适配非交互式环境。

解决方案

1. 修正/etc/sudoers配置

使用visudo命令编辑/etc/sudoers,确保命令匹配正确:

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
jenkins ALL=(ALL) NOPASSWD: /bin/cp
jenkins ALL=(ALL) NOPASSWD: /bin/kill
jenkins ALL=(ALL) NOPASSWD: /bin/chown
jenkins ALL=(ALL) NOPASSWD: /bin/su - shoeshop -c *
# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers

说明:

  • /bin/cp直接指定命令,sudo允许该命令带任意参数执行;
  • /bin/su - shoeshop -c *允许jenkins用户通过su切换到shoeshop并执行任意命令(若需更严格权限,可替换*为具体命令路径)。

2. 修正Jenkinsfile中的命令

pipeline {
    agent {
        label 'gitlab-server'
    }
    tools {
        maven '3.6.3'
    }
    environment {
        appUser = "shoeshop"
        appName = "shoe-ShoppingCart"
        appVersion = "0.0.1-SNAPSHOT"
        appType = "jar"
        processName = "${appName}-${appVersion}.${appType}"
        folderDeploy = "/datas/${appUser}"
        buildScript = "mvn clean install -DskipTests=True"
        // 移除密码传递,直接使用sudo
        copyScript = "sudo cp -r target/${processName} ${folderDeploy}"
        permsScript = "sudo chown -R ${appUser}:${appUser} ${folderDeploy}"
        // 增加错误忽略,避免无进程时pipeline失败
        killScript = "sudo kill -9 \$(ps -ef| grep ${processName} | grep -v grep | awk '{print \$2}') 2>/dev/null || true"
        // 改用sudo -u指定用户,并用双引号确保变量解析
        runScript = "sudo -u ${appUser} bash -c \"cd ${folderDeploy}; java -jar ${processName} > nohup.out 2>&1 &\""
    }
    stages {
        stage('build') {
            steps {
                sh (script: """ ${buildScript} """, label: "build with maven")
            }
        }
        stage('deploy') {
            steps {
                sh (script: """ ${copyScript} """, label: "copy the .jar file into deploy folder")
                sh (script: """ ${permsScript} """, label: "set permission folder")
                sh (script: """ ${killScript} """, label: "terminate the running process")
                sh (script: """ ${runScript} """, label: "run the project")
            }
        }
    }
}

关键修改点:

  • 移除echo '123' | sudo -S,依赖NOPASSWD权限直接执行sudo命令;
  • killScript增加2>/dev/null || true,避免因目标进程不存在导致pipeline中断;
  • runScript改用sudo -u ${appUser}替代sudo su,无需终端交互,同时用双引号包裹确保变量正确解析;
  • permsScript修正为${appUser}:${appUser},明确用户组。

3. 验证配置

执行以下命令测试jenkins用户的sudo权限(在GitLab服务器上切换到jenkins用户):

sudo cp test.txt /datas/shoeshop/
sudo chown -R shoeshop:shoeshop /datas/shoeshop/
sudo -u shoeshop bash -c "echo test > /datas/shoeshop/test.log"

若以上命令无需输入密码即可执行,说明权限配置生效。

内容的提问来源于stack exchange,提问作者Minh Quang Trần

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:24:53