การซ้อนคำสั่ง execer run / run shell


15

แนะนำสั้น ๆ เกี่ยวกับกรณีการใช้งาน:

ฉันใช้dockerภาชนะที่จะทำงานของฉันการทดสอบโดยใช้go นี้สามารถทำได้อย่างง่ายดายโดยใช้go test ./... docker exec <container> /bin/sh -c "go test ./..."น่าเสียดายที่go test ./...ทำงานในไดเรกทอรีย่อยทั้งหมดและฉันต้องการยกเว้นหนึ่งไดเรกทอรี (ไดเรกทอรีผู้ขาย)

ทางออกที่แนะนำสำหรับสิ่งนี้คือการใช้คำสั่งต่อไปนี้: go test $(go list ./... | grep -v '<excluded>'อย่างใดนี้ทำให้ฉันกับผลลัพธ์ต่อไปนี้:

docker run golang:1.6.2-alpine /bin/sh -c "go test " (ฉันได้ทดสอบสิ่งนี้ทั้งการรันและการประมวลผล แต่พวกเขาอาจใช้แกนเดียวกัน)

เมื่อฉัน ssh ลงในภาชนะที่ใช้docker exec -it <container_id> /bin/shและเรียกใช้คำสั่งเดียวกันแน่นอนมันทำงานเหมือนมีเสน่ห์

ดูเหมือนว่าการเรียกใช้คำสั่งเชลล์ในรางที่นักเรียกใช้ / รันไม่สนับสนุนคำสั่งใด ๆ ที่ซ้อนอยู่ด้วย$()?


คุณเรียกใช้คำสั่งอะไรกันแน่ ใน$(go list ./... | grep -v '<excluded>'สิ่งที่เป็น<excluded>คืออะไร?
cuonglm

มันเป็นไดเรกทอรีvendorเช่น
Wesley van Opdorp

4
ตกลงดังนั้นโปรดทราบว่า$(...)เชลล์ของคุณถูกขยายในเครื่องหมายคำพูดคู่ก่อนที่มันจะทำงานในคอนเทนเนอร์นักเทียบท่า ดังนั้นปัญหาอาจมาจากเนื้อหาไดเรกทอรีปัจจุบันของคุณ ไม่docker exec container /bin/sh -c 'go test $(go list ./... | grep -v "<excluded>")'ทำงานหรือไม่
cuonglm

ทำไมไม่เรียกใช้คำสั่งจากสคริปต์ ?
030

คำตอบ:


30

คำสั่งของคุณอาจไม่ทำงานตามที่คุณคาดหวังจากการใช้ bash gotcha ทั่วไป:

docker exec <container> /bin/sh -c "go test $(go list ./... | grep -v '<excluded>')"

คำสั่งที่คุณพยายามเรียกใช้จะทำการขยายตัวของ subshell $()บนโฮสต์ของคุณเพราะมันอยู่ในเครื่องหมายคำพูดคู่

สิ่งนี้สามารถแก้ไขได้โดยการอ้างคำสั่งของคุณเพียงคำเดียวโดย @cuonglm ในความคิดเห็นของคำถาม

docker exec <container> /bin/sh -c 'go test $(go list ./... | grep -v "<excluded>")'

แก้ไข: ตัวอย่างเล็กน้อย

[wbarnwell@host ~]$ docker run -it --rm busybox /bin/sh -c '$(whoami)'
/bin/sh: root: not found
[wbarnwell@host ~]$ docker run -it --rm busybox /bin/sh -c "$(whoami)"
/bin/sh: wbarnwell: not found

0

จากgo test --help:

-run regexp     Run only those tests and examples matching the regular
                expression.

ดังนั้นฉันเดาว่าgo test -run "(!vendor)" ./...จะข้ามโฟลเดอร์นั้นไป


ขอบคุณ Marcel งานนี้! น่าเสียดายที่มันไม่แสดงรายการไดเรกทอรีทั้งหมดที่ไม่ตรงกับการทดสอบใด ๆ - รายการไดเรกทอรีผู้จำหน่ายทั้งหมดด้วย "ไม่มีไฟล์ทดสอบ"
Wesley van Opdorp

คุณสามารถกรองเหล่านั้นได้เสมอ:$(go test -run "(!vendor)" ./... | egrep -v "no test files\|vendor")
Marcel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.