Shell Script mktemp วิธีที่ดีที่สุดในการสร้าง pipe ที่มีชื่อชั่วคราวคืออะไร?


30

ฉันทราบดีที่สุดว่าควรสร้างไฟล์ชั่วคราวด้วยmktempแต่จะมีชื่อไพพ์ว่าอย่างไร

ฉันชอบสิ่งที่จะเป็นไปตาม POSIX ที่สุดเท่าที่จะทำได้ แต่ Linux เท่านั้นที่ยอมรับได้ หลีกเลี่ยง Bashisms dashเป็นเกณฑ์อย่างหนักของฉันเท่านั้นที่ผมเขียน

คำตอบ:


41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

ซึ่งแตกต่างจากการสร้างไฟล์ปกติซึ่งมีแนวโน้มที่จะถูกแย่งชิงโดยไฟล์ที่มีอยู่หรือลิงก์สัญลักษณ์การสร้างเนมไปป์mkfifoหรือฟังก์ชั่นพื้นฐานจะสร้างไฟล์ใหม่ในตำแหน่งที่ระบุหรือล้มเหลว บางอย่างที่: >fooไม่ปลอดภัยเพราะหากผู้โจมตีสามารถทำนายผลลัพธ์ของmktempการโจมตีผู้โจมตีสามารถสร้างไฟล์เป้าหมายสำหรับตัวเอง แต่mkfifo fooจะล้มเหลวในสถานการณ์ดังกล่าว

หากคุณต้องการการพกพา POSIX แบบเต็มรูปแบบmkfifo -m 600 /tmp/myfifoจะปลอดภัยต่อการหักหลัง แต่มีแนวโน้มที่จะปฏิเสธการให้บริการ หากไม่สามารถเข้าถึงตัวสร้างชื่อไฟล์แบบสุ่มได้คุณจะต้องพยายามลองใหม่

หากคุณไม่สนใจปัญหาความปลอดภัยเล็กน้อยเกี่ยวกับไฟล์ชั่วคราวคุณสามารถทำตามกฎง่าย ๆ : สร้างไดเรกทอรีส่วนตัวและเก็บทุกอย่างไว้ในนั้น

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"

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

1
คำสั่ง trap ไม่ควรtrap "rm -rf '$tempdir'" EXIT HUP INT TERMใช่หรือไม่ กับดักสามารถทำมันเป็นของตัวเองขยายตัวแปร?
หก

@Six คำสั่งของคุณจะขยาย$tempdirในเวลาที่trapคำสั่งถูกประเมินไม่ใช่เวลาที่กับดักถูกทริกเกอร์ ในกรณีนี้มันไม่ได้สร้างความแตกต่างใด ๆ ยกเว้นว่ารหัสของคุณจะแบ่งออกอย่างน่ากลัวหากมูลค่าของtempdirมีคำพูดเดียวในขณะที่รหัสของฉันทำงานได้เสมอ
Gilles 'หยุดความชั่วร้าย' ใน

@Gilles นั่นเป็นคุณสมบัติที่ดี ฉันลองตัวอย่างคำพูดเดียวโดยไม่มีโชคดังนั้นฉันจึงคิดว่ากับดักไม่สามารถประเมินตัวแปรได้ในขณะทำงาน มันกลับกลายเป็นว่า$tempdirมีการประกาศในพื้นที่ของฉันและจะต้องมีการกำหนดทั่วโลกเพื่อให้กับดักเข้าถึงได้ เข้าท่าตอนนี้ ...
6

1
@Gilles ... ตราบใดที่$tempdir ค่าไม่เปลี่ยนแปลงเช่นกันซึ่งเป็นที่ยอมรับสำหรับวัตถุประสงค์ทั่วไป เพียงระวังอย่าใช้ชื่อเดียวกันในการสร้างไฟล์ชั่วคราวหลายไฟล์ / dirs ...
MestreLion

3

ทางเลือกที่ปลอดภัยกว่าคือการใช้mktempเพื่อสร้างไดเรกทอรีอย่างปลอดภัยจากนั้นใส่ไพพ์ที่มีชื่อของคุณไว้ในไดเรกทอรีนั้นทำการลบrm -R $dirทิ้งในที่สุด


ฉันเลือกที่จะสร้าง FIFO ในmktempไดเรกทอรีเนื่องจากเป็นคำตอบเดียวที่ยอมรับได้จริงๆในกรณีที่คุณไม่ได้สังเกตเห็น @Gilles โพสต์คำตอบนี้ในเชิงลึกแล้ว
JM Becker

2

ใช้ตัวเลือก "dry-run":

mkfifo $(mktemp -ut pipe.XXX)

1
ตามหน้า man การใช้-uตัวเลือก "ไม่ได้รับการสนับสนุน"
dogbane

@dogbane ดังนั้นการใช้งาน-tแต่ตราบใดที่มันทำงานได้อย่างน่าเชื่อถือฉันจะไปกับมัน
polemon

ขอโทษมันบอกว่า-tท้อที่ไหน?
dogbane

2
@dogbane ถ้ามันสำคัญมากฉันจะสร้างแอพพลิเคชั่น C เล็ก ๆ ขึ้นมาเรียกใช้mkstemp()ฟังก์ชัน ( linux.die.net/man/3/mkstemp ) -tสวิทช์ไม่ได้ท้อแท้มันเป็น-pที่ไม่ดีของฉัน
polemon

1

คุณสามารถใช้mktempเพื่อสร้างไฟล์ชั่วคราวจากนั้นลบมันและสร้างไปป์ที่มีชื่อด้วยชื่อเดียวกัน

ตัวอย่างเช่น:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}

การลบ$TMPPIPEก่อนที่จะmkfifoหลีกเลี่ยงปัญหา 'ไม่ปลอดภัย' ที่เกี่ยวข้องTMPPIPE=`mktemp -u` ; mkfifo $TMPPIPEหรือไม่
JM Becker

1
@TechZilla mkfifoปลอดภัยจริง ๆ ไม่เหมือนกับการสร้างไฟล์ปกติจากเชลล์ ถ้าไม่ใช่การสร้างไฟล์แล้วการลบไฟล์นั้นจะไม่ช่วยเลย (อันที่จริงแล้วมันจะช่วยอำนวยความสะดวกให้กับงานของผู้โจมตีได้มากโดยไม่ต้องให้เขาเดาชื่อไฟล์) ดังนั้นคำตอบของ dogbane ใช้งานได้ แต่การสร้างไฟล์ระดับกลางเป็นภาวะแทรกซ้อนที่ไร้ประโยชน์
Gilles 'หยุดความชั่วร้าย'

1
@Gilles คุณรู้ในสิ่งที่เกี่ยวกับmktempหน้าคนที่เรียกว่า-uตัวเลือก 'ไม่ปลอดภัย'?
JM Becker

@dogbane ฉันโหวตให้กับคำตอบของคุณและความคิดเห็นของคุณที่ฉันรู้สึกว่ามั่นคง แม้ว่าฉันจะเสร็จสิ้นเมื่อวานนี้ .. ฉันแค่รอที่จะเห็นเมื่อมีคนโพสต์โซลูชันของฉันหรือหวังว่าจะดีขึ้น ดังนั้นแม้ว่าฉันจะใช้mktemp -dคุณยังคงมีบางจุดสำหรับการป้อนข้อมูลของคุณ ขอบคุณสำหรับความช่วยเหลือของคุณฉันขอขอบคุณจริงๆ!
JM Becker

1
@TechZilla mktemp -uไม่ปลอดภัยเมื่อสร้างไฟล์ปกติเพราะให้การป้องกันการปฏิเสธการบริการ (หากชื่อที่สร้างไว้ไม่แน่นอนพอ) แต่ไม่ป้องกันผู้โจมตีจากการสร้างไฟล์ภายใต้จมูกของโปรแกรม การสร้างฟีฟ่าแทนที่จะเป็นไฟล์ปกติเป็นกรณีการใช้งานที่หายากซึ่งหน้าคนไม่ได้พูดถึง
Gilles 'หยุดความชั่วร้าย'

0

ใช้mkfifoหรือmknodใน Unix โดยกระบวนการที่แยกกันสองกระบวนการสามารถเข้าถึงไปป์ตามชื่อ - กระบวนการหนึ่งสามารถเปิดเป็นผู้อ่านและอื่น ๆ ในฐานะนักเขียน

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

ไปป์ที่มีชื่อสามารถลบได้เช่นเดียวกับไฟล์ใด ๆ :

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipe สามารถใช้ไฟล์ปกติสำหรับการอ่านเพียงครั้งเดียว

http://www.linuxjournal.com/article/2156


2
mkfifoฉันตระหนักดีเกี่ยวกับท่อชื่อและ มันไม่ได้ตอบคำถามของฉันเกี่ยวกับไพพ์ที่มีชื่อmkdirชั่วคราว
JM Becker

2
วิธีนี้แก้ไขปัญหาที่mktempอยู่ในการสร้างไปป์ที่มีชื่ออย่างปลอดภัยได้อย่างไร
camh

1
โอ้ตกลงที่ดีที่สุดคือการสร้างพวกเขาภายใต้ / tmp พวกเขาเป็นไฟล์ชั่วคราวตามคำนิยามและจะล้างออกเมื่อรีบูตระบบ หรือดีกว่านั้นมีฟังก์ชั่นของเชลล์ซึ่งจะสร้าง namedpipe จากmktempผลลัพธ์เอง (ofcourse โดยการลบไฟล์ temp ก่อนแล้วจึงเรียกใช้mkfifoบนเดิม) mktempยังสามารถใช้เพื่อสร้างไดเรกทอรีชั่วคราวลองด้วย-t -dสวิตช์
Nikhil Mulley
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.