วิธี echo คำสั่งในสคริปต์เปลือก bash แต่ไม่รันพวกเขา?


11

มีวิธีการรันเชลล์สคริปต์ด้วยการสะท้อนคำสั่งแต่ไม่มีการรันคำสั่งเหล่านั้นหรือไม่?

สมมติว่าฉันมีสคริปต์ลบไฟล์ที่มีชื่อถูกเก็บไว้ในตัวแปร:

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

การเพิ่มset -vจะสะท้อนคำสั่งต่อไปนี้ก่อนที่จะดำเนินการ:

$ ./scr.sh
FN="filename"
rm -f ${FN}

ตอนนี้ฉันต้องการที่จะเห็นการไหลของสคริปต์นี้โดยไม่ต้องลบไฟล์จริง IOW ฉันต้องการป้องกันผลกระทบใด ๆ ต่อสภาพแวดล้อมภายนอกและระบบไฟล์ เป็นไปได้ไหม

ฉันสามารถห่อคำสั่งทั้งหมดด้วยechoคำสั่ง แต่มันเหนื่อยสำหรับสคริปต์ยาว


ฉันไม่ใช่ผู้เชี่ยวชาญการเขียนสคริปต์ bash แต่ถ้าฉันจะเขียนด้วยภาษาการเขียนโปรแกรมอื่นฉันจะเก็บคำสั่งทั้งหมดในอาร์เรย์ วิธีนี้ควรง่ายต่อการวนซ้ำและดำเนินการคำสั่งหรือพิมพ์ออกมา
hugo der hungrige

คำตอบ:


8

ไม่มีวิธีที่จะผ่านสคริปต์เพื่อดูว่ามันจะทำงานโดยไม่ทำอย่างนั้นจริง ๆ ในตัวอย่างของคุณไม่มีifคำสั่งหรือลูป แต่ในสคริปต์จริงมักมีคำสั่งที่มีเงื่อนไขจำนวนมาก สาขาใดจะถูกยึดมักจะขึ้นอยู่กับสิ่งที่เกิดขึ้นเมื่อเชลล์รันคำสั่งก่อนหน้า หากมันไม่ได้รันคำสั่งไม่มีวิธีใดที่เชลล์จะรู้ได้ว่าเอาต์พุตนั้นจะสร้างขึ้นมาหรือสิ่งใดที่โค้ดส่งคืนควรเป็นอะไร

หากประเด็นคือคุณต้องการกลั่นกรองสคริปต์และรู้ว่าจะทำอะไรก่อนที่จะเรียกใช้นั่นไม่ใช่ความคิดที่ไม่ดี แต่แนบเนียนเกี่ยวกับวิธีการที่ดีที่สุดที่จะทำคือโดยเพียงแค่การเรียกดูไฟล์ที่มีlessหรือviหรือสิ่งที่คล้ายกัน

ที่เพิ่ม

หากคุณกำลังพัฒนาสคริปต์และคุณต้องการก้าวผ่านมันเป็นครั้งแรกการทดสอบตรรกะ แต่ไม่ได้ทำความเสียหายจริง ๆ หากคุณมีข้อผิดพลาดโซลูชันที่ฉันมักจะสามารถใช้ได้คือการแก้ไขเท่านั้น ข้อความที่สามารถทำความเสียหายใด ๆ โดยการวางechoลงบนด้านหน้า

สิ่งนี้มักใช้งานได้กับสคริปต์ทั่วไปในชีวิตจริงเพราะ (ก) การสร้างรายการที่คุณจะวนซ้ำหรือค่าที่คุณตั้งค่าตัวแปรมักจะสามารถสร้างขึ้นได้โดยไม่ต้องเปลี่ยนระบบไฟล์และ (b) ก็เพียงพอที่จะ สมมติว่าถ้าคุณรันคำสั่งมันจะสำเร็จ


ขอบคุณ มันจะทำให้ฉันประหลาดใจถ้ามีวิธีแน่นอนเนื่องจากเหตุผลที่คุณพูดถึง แต่ฉันตัดสินใจที่จะลองต่อไป เหตุผลนี้คือฉันกำลังพัฒนาสคริปต์ที่ย้ายไฟล์ข้ามเครื่องจำนวนมากในเครือข่ายและดำเนินการบางอย่างกับโฮสต์ระยะไกล ฉันต้องการดูสคริปของสคริปต์ก่อนที่จะยอมรับการเปลี่ยนแปลงในระบบไฟล์ มันจะเป็นเพียงแค่เป็นที่น่าเบื่อไปกว่าทุกเครื่องจากระยะไกลผิดพลาด file ที่ถูกต้อง ...
ysap

1
เพิ่มเติม: ในการก้าวผ่านสคริปต์คุณสามารถเริ่มต้นสคริปต์trap read debugที่จะอ่านหลังจากทุกบรรทัดที่ดำเนินการแล้วและคุณสามารถก้าวผ่านสคริปต์ช้าๆด้วยการป้อน (ซึ่งมีประโยชน์ถ้าคุณมีสคริปต์ที่ยาวมากและต้องการทดสอบ เป็นครั้งแรก)
netigger

8

ฉันคิดว่าคุณจะต้องก้อง - แต่ถ้าคุณใส่คำสั่งในตัวแปรคุณสามารถเปิดและปิด นอกจากนี้คำสั่งยังสามารถใช้เป็นฟังก์ชั่นและซับซ้อนตามที่คุณต้องการ

#!/bin/bash
echo 'Debug'
  D=echo
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy
echo $'\n\nLive'
  D=
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy

!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy

Live -rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy ls: cannot access testy: No such file or directory


ฉันต้องการอัญประกาศในคำสั่ง echo / Don't-echo แล้วต้องใช้D=evalในส่วนที่ถ่ายทอดสด แต่คำตอบที่ดี!
แจสเปอร์

5

คุณติดตามโฟลว์โดยใช้อ็อพชัน -x สำหรับ bash แต่จะยังคงเรียกใช้งานคำสั่ง

สิ่งที่ดีที่สุดที่คุณทำได้คือใส่ echo หรือคอมเม้นท์คำสั่งที่มีเอฟเฟกต์ภายนอกเช่น rm อย่างน้อยคุณก็ไม่จำเป็นต้องเปลี่ยนทุกบรรทัด


ขอบคุณ ฉันพูดถึงตัวเลือกนั้นในคำถามของฉัน แต่มันไม่ได้แก้ปัญหาของฉัน
ysap

ขออภัยฉันคิดว่าคุณหมายถึงการสะท้อนทุกบรรทัด -x จะลดคำสั่งนี้เป็นคำสั่งเล็กน้อยและแสดงการประเมินผลให้คุณ
parkydr

4

ฉันไม่ทราบวิธีการเฉพาะสำหรับการใช้งานแบบแห้ง แต่เราสามารถใช้ข้อควรระวังบางอย่างเพื่อทำความเข้าใจสคริปต์ที่ไม่รู้จัก

  1. ใช้สภาพแวดล้อมchrootเพื่อรันสคริปต์ดีบักของคุณ มันจะทำหน้าที่เป็นแซนด์บ็อกซ์และจะให้การป้องกันการลบ / แก้ไขไฟล์ระบบหลัก
  2. ใช้bash -n <script>สำหรับการตรวจสอบไวยากรณ์ จากคู่มือ gnu bash https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

-n Read commands but do not execute them; this may be used to check a script for syntax errors. This option is ignored by interactive shells.

  1. อ่านสคริปต์อย่างน้อยหนึ่งครั้ง คุณสามารถใช้คำสั่งเสียงสะท้อนสำหรับการแก้ปัญหาดังกล่าวในคำตอบโดย user191016
    • ระวังโค้ดที่น่าสงสัยหรืออันตราย
    • เช่นที่เกี่ยวข้องกับ rm คำสั่งที่มีผลต่อ / dev / sda เป็นต้น
  2. พยายามเรียกใช้สคริปต์ในฐานะผู้ใช้ปกติหลีกเลี่ยงการเรียกใช้สคริปต์ที่ไม่รู้จักในฐานะรูท
  3. คุณสามารถกำหนดนามแฝงที่จะทำให้คำสั่งที่สามารถปรับเปลี่ยนไฟล์เป็นแบบโต้ตอบที่เริ่มต้นของสคริปต์ของคุณตัวอย่าง alias rm="rm -i" alias cp="cp -i" alias mv="mv -i" สำหรับการแก้ไขกระแสเช่น sed sed -i(-i แก้ไขไฟล์ในสถานที่โดยไม่ต้อง -i มันทำงานแห้งสำหรับ sed ให้ตรวจสอบหน้าคนสำหรับรายละเอียด) สามารถคัดลอกคำสั่งเต็มรูปแบบและเรียกใช้ ก่อนคำสั่งจริงมันจะแสดงผลลัพธ์บนหน้าจอจากนั้นใช้คำสั่งเพื่อรออินพุตของผู้ใช้เพื่อดำเนินการต่อ ตัวอย่าง sed -i <pattern> แทนที่ด้วย sed <pattern> read -p "Press any key..." sed -i <pattern>

นอกจากนี้ขอแนะนำเสมอให้เก็บจุดสำรองในระบบของคุณดังนั้นในกรณีที่ข้อมูลฉุกเฉินสามารถกู้คืนได้


3

ทำset –nหรือต่อท้ายคำสั่งnที่มีอยู่ของคุณ set –vแต่เนื่องจากสิ่งนี้ทำให้เชลล์ไม่ต้องประเมินคำสั่งใด ๆ แม้แต่ifหรือwhileคุณอาจไม่ได้รับมุมมองที่ดีเกี่ยวกับโฟลว์การดำเนินงาน


ขอบคุณ นี่เป็นการเริ่มต้นที่ดี แต่อย่างที่คุณพูดถึงมันไม่ให้ฉันเห็นโฟลว์จริง - ในสคริปต์จริงของฉันฉันมีลูปมากกว่ารายการโฮสต์ระยะไกล
ysap

3

นี่เป็นโครงสร้างเล็กน้อยที่ฉันชอบใช้:

#!/bin/sh

verbose=false
really=true

# parse arguments
while [ $# -ge 1 ]
do
  case "$1" in
    -v) verbose=true ;;
    -n) really=false; verbose=true ;;
  esac
  shift
done

doCmd() {
  if $verbose; then echo "$@"; fi
  if $really; then "$@"; fi
}

doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah

2

หากคุณต้องการป้องกันการดัดแปลงเกิดขึ้นคุณสามารถเรียกใช้สคริปต์ในฐานะผู้ใช้ที่ไม่มีสิทธิ์:

sudo -u nobody ./scr.sh

ในตัวอย่างของคุณสิ่งนี้จะดำเนินการFN="filename"ตามปกติ ในขณะที่มันดำเนินการทางเทคนิคคำสั่งrm -f ${FN}เช่นกันจะไม่มีอะไรเกิดขึ้นหากไม่มีใครไม่มีสิทธิ์ที่จำเป็นในการลบไฟล์

แน่นอนว่าสิ่งนี้จะทำให้เกิดปัญหากับเวิร์กโฟลว์ตามเงื่อนไข ความจริงที่ว่าrmคำสั่งล้มเหลวอาจส่งผลต่อส่วนอื่น ๆ ของสคริปต์


สิ่งที่เราจะไม่มีวันเข้าใจ: ทำไมต้องรูทเพื่อที่จะทำงานอย่างที่ไม่มีใคร ...
mjohnsonengr

ผู้ใช้ "none" ไม่ได้เป็นส่วนสำคัญของระบบปฏิบัติการ แต่คุณสามารถเพิ่มรายการในไฟล์ sudoers ที่อนุญาตให้ใช้รหัสผ่าน sudo สำหรับ "none"
เดนนิส

ไม่รู้สินะ. ดูเหมือนว่าสคริปต์จะยุติเนื่องจากข้อผิดพลาดหรืออื่นก่อนที่จะเสร็จสิ้น
Edward Falk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.