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

