ฉันมีสิ่งนี้ใน Jenkinsfile (Groovy) และฉันต้องการบันทึก stdout และรหัสทางออกในตัวแปรเพื่อใช้ข้อมูลในภายหลัง
sh "ls -l"
ฉันจะทำสิ่งนี้ได้อย่างไรโดยเฉพาะอย่างยิ่งเนื่องจากดูเหมือนว่าคุณไม่สามารถเรียกใช้โค้ด Groovy ใด ๆ ภายในJenkinsfile
?
ฉันมีสิ่งนี้ใน Jenkinsfile (Groovy) และฉันต้องการบันทึก stdout และรหัสทางออกในตัวแปรเพื่อใช้ข้อมูลในภายหลัง
sh "ls -l"
ฉันจะทำสิ่งนี้ได้อย่างไรโดยเฉพาะอย่างยิ่งเนื่องจากดูเหมือนว่าคุณไม่สามารถเรียกใช้โค้ด Groovy ใด ๆ ภายในJenkinsfile
?
คำตอบ:
ไปป์ไลน์เวอร์ชันล่าสุดsh
ช่วยให้คุณสามารถทำสิ่งต่อไปนี้
// Git committer email
GIT_COMMIT_EMAIL = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"
คุณสมบัติอื่นเป็นreturnStatus
ตัวเลือก
// Test commit message for flags
BUILD_FULL = sh (
script: "git log -1 --pretty=%B | grep '\\[jenkins-full]'",
returnStatus: true
) == 0
echo "Build full flag: ${BUILD_FULL}"
ตัวเลือกเหล่านี้ที่เพิ่มขึ้นอยู่กับนี้ปัญหา
ดูเอกสารประกอบอย่างเป็นทางการสำหรับsh
คำสั่ง
WorkflowScript: 97: Expected a step @ line 97, column 17.
script
บล็อกขั้นตอนเท่านั้น jenkins.io/doc/book/pipeline/syntax/#declarative-steps
เวอร์ชันปัจจุบันของ Pipeline รองรับreturnStdout
และreturnStatus
ทำให้สามารถรับเอาต์พุตหรือสถานะจากsh
/ bat
steps
ตัวอย่าง:
def ret = sh(script: 'uname', returnStdout: true)
println ret
script { }
ขั้นตอน
คำตอบอย่างรวดเร็วคือ:
sh "ls -l > commandResult"
result = readFile('commandResult').trim()
ฉันคิดว่ามีคำขอคุณลักษณะเพื่อให้สามารถรับผลลัพธ์ของขั้นตอนการดวลจุดโทษได้ แต่เท่าที่ฉันรู้ในปัจจุบันไม่มีตัวเลือกอื่น
แก้ไข: JENKINS-26133
EDIT2: ไม่แน่ใจตั้งแต่รุ่นใด แต่ตอนนี้ sh / bat สามารถคืนเอาต์พุต std ได้ง่ายๆ:
def output = sh returnStdout: true, script: 'ls -l'
หากคุณต้องการได้รับ stdout และทราบว่าคำสั่งประสบความสำเร็จหรือไม่เพียงใช้returnStdout
และห่อในตัวจัดการข้อยกเว้น:
ไพพ์ไลน์สคริปต์
try {
// Fails with non-zero exit if dir1 does not exist
def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim()
} catch (Exception ex) {
println("Unable to read dir1: ${ex}")
}
ผลลัพธ์ :
[Pipeline] sh
[Test-Pipeline] Running shell script
+ ls -la dir1
ls: cannot access dir1: No such file or directory
[Pipeline] echo
unable to read dir1: hudson.AbortException: script returned exit code 2
น่าเสียดายที่ hudson.AbortException ไม่มีวิธีที่มีประโยชน์ใด ๆ ในการรับสถานะการออกนั้นดังนั้นหากจำเป็นต้องใช้ค่าจริงคุณจะต้องแยกมันออกจากข้อความ (ugh!)
ขัดกับ Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.htmlสร้างจะไม่ล้มเหลวเมื่อข้อยกเว้นนี้ถูกจับได้ มันล้มเหลวเมื่อไม่ได้จับ!
อัปเดต: หากคุณต้องการให้เอาต์พุต STDERR จากคำสั่งเชลล์เจนกินส์น่าเสียดายที่ไม่สามารถรองรับกรณีใช้งานทั่วไปได้อย่างถูกต้อง 2017 ตั๋วJENKINS-44930ติดอยู่ในสถานะปิงปิงที่มีความเห็นในขณะที่ยังไม่มีความคืบหน้าในการแก้ปัญหาโปรดพิจารณาเพิ่ม upvote ของคุณลงไป
สำหรับวิธีแก้ปัญหาในตอนนี้อาจมีวิธีการสองวิธีที่เป็นไปได้
a) Redirect STDERR ไปยัง STDOUT 2>&1
- แต่มันก็ขึ้นอยู่กับคุณแล้วว่าจะแยกออกจากเอาท์พุทหลักและคุณจะไม่ได้รับผลลัพธ์ถ้าคำสั่งล้มเหลว - เพราะคุณอยู่ในตัวจัดการข้อยกเว้น
b) เปลี่ยนเส้นทาง STDERR ไปยังไฟล์ชั่วคราว (ชื่อที่คุณเตรียมไว้ก่อนหน้านี้) 2>filename
(แต่อย่าลืมล้างไฟล์ในภายหลัง) - เช่น รหัสหลักจะกลายเป็น:
def stderrfile = 'stderr.out'
try {
def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim()
} catch (Exception ex) {
def errmsg = readFile(stderrfile)
println("Unable to read dir1: ${ex} - ${errmsg}")
}
c) ไปทางอื่นตั้งreturnStatus=true
แทนแจกจ่ายด้วยตัวจัดการข้อยกเว้นและจับผลลัพธ์ไปยังไฟล์เช่น:
def outfile = 'stdout.out'
def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true)
def output = readFile(outfile).trim()
if (status == 0) {
// output is directory listing from stdout
} else {
// output is error message from stderr
}
ข้อแม้: รหัสข้างต้นเป็น Unix / Linux เฉพาะ - Windows ต้องการคำสั่งเชลล์ที่แตกต่างอย่างสิ้นเชิง
นี่เป็นกรณีตัวอย่างซึ่งจะทำให้รู้สึกว่าฉันเชื่อ!
node('master'){
stage('stage1'){
def commit = sh (returnStdout: true, script: '''echo hi
echo bye | grep -o "e"
date
echo lol''').split()
echo "${commit[-1]} "
}
}
สำหรับผู้ที่ต้องการใช้เอาต์พุตในคำสั่งเชลล์ที่ตามมาแทนที่จะเป็น Groovy สิ่งที่ตัวอย่างเช่นนี้สามารถทำได้:
stage('Show Files') {
environment {
MY_FILES = sh(script: 'cd mydir && ls -l', returnStdout: true)
}
steps {
sh '''
echo "$MY_FILES"
'''
}
}
ฉันพบตัวอย่างในโค้ด mavenว่ามีประโยชน์มาก
วิธีที่ง่ายที่สุดคือใช้วิธีนี้
my_var=`echo 2`
echo $my_var
ผลลัพธ์: 2
โปรดทราบว่าไม่ใช่คำพูดเดียวที่ง่ายคืออ้างกลับ (`)
sh
มิฉะนั้นผู้คนอาจคิดว่ามันเป็นเรื่องใหญ่โดยเฉพาะอย่างยิ่งหากพวกเขาไม่คุ้นเคยกับการใช้สคริปต์ทุบตี ฉันเพิ่งลองใช้กับ Jenkins ใช้ls -l
แทนecho 2
และใช้งานได้ ฉันเคยใช้วิธีการนี้มาก่อน แต่เคยค้นหาวิธีอื่นเนื่องจากไม่น่าเชื่อถือ ฉันมีเอาต์พุตของคำสั่งที่ซับซ้อนมากขึ้นที่จับบนเชลล์มาตรฐานด้วยวิธีนี้ แต่เมื่อย้ายไปที่เจนกินส์sh
ตัวแปรจะไม่เก็บค่าอะไรไว้ด้วยเหตุผลบางอย่างที่ไม่ทราบสาเหตุ