เปลี่ยนเส้นทางไปยัง / dev / null


144

ฉันกำลังอ่านสคริปต์เปลือกทุบตีตัวอย่าง:

#!/bin/bash

# This script makes a backup of my home directory.

cd /home

# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1

# First remove the old bzip2 file.  Redirect errors because this generates some if the archive
# does not exist.  Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar

# Copy the file to another host - we have ssh keys for making this work without intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1

# Create a timestamp in a logfile.
date >> /home/franky/log/home_backup.log
echo backup succeeded >> /home/franky/log/home_backup.log

ฉันพยายามเข้าใจการใช้ "/ dev / null 2> & 1" ที่นี่ ตอนแรกฉันคิดว่าสคริปต์นี้ใช้ / dev / null เพื่อละเว้นข้อผิดพลาดอย่างงดงามโดยไม่ทำให้สคริปต์ขัดข้อง (เช่นลองจับข้อยกเว้นในภาษาการเขียนโปรแกรม) เนื่องจากฉันไม่เห็นวิธีการใช้ tar ในการบีบอัดไดเรกทอรีลงในไฟล์ tar อาจทำให้เกิดข้อผิดพลาดประเภทใด ๆ


3
การเปลี่ยนเส้นทางไปที่/dev/nullจะไม่ป้องกันการหยุดทำงาน แต่จะทำความสะอาดสตรีมเอาต์พุต stdout และ stderr tarอาจทำให้เกิดข้อผิดพลาดได้หลายวิธี คุณอาจไม่มีสิทธิ์ในการเขียนไฟล์อาจมีอยู่แล้วเป็นต้น
Sparhawk

3
เป็นเพียงเคล็ดลับในการหลีกเลี่ยงผลลัพธ์ที่ไม่จำเป็น สำหรับสาเหตุที่ tar สามารถทำให้เกิดข้อผิดพลาด: เนื่องจากไดเรกทอรีเป้าหมายไม่มีอยู่เนื่องจากแหล่งข้อมูลไม่ได้เพราะคุณไม่มีสิทธิ์เข้าถึงเขียนไปยังเป้าหมายหรืออ่านไปยังแหล่งข้อมูลเพราะtarไม่ได้อยู่ใน $ PATH ของคุณเพราะtarเกิดข้อผิดพลาด (คุณไม่มีทางรู้) เพราะไม่มีพื้นที่เหลือบนอุปกรณ์เนื่องจากtarเวอร์ชันเปลี่ยนไปและตอนนี้ต้องใช้ไวยากรณ์ที่แตกต่างกันเนื่องจากดิสก์ทำให้เกิดข้อผิดพลาด I / O ฉันแน่ใจว่าคุณสามารถหาข้อมูลเพิ่มเติมได้
terdon

คำตอบ:


223

ไม่สิ่งนี้จะไม่ป้องกันสคริปต์จากการขัดข้อง หากข้อผิดพลาดใด ๆ ที่เกิดขึ้นในtarกระบวนการ (เช่น: สิทธิ์ถูกปฏิเสธไม่มีไฟล์หรือไดเรกทอรีดังกล่าว, ... ) สคริปต์จะยังคงผิดพลาด

เนื่องจากการใช้> /dev/null 2>&1จะเปลี่ยนเส้นทางเอาต์พุตคำสั่งทั้งหมดของคุณ (ทั้งstdoutและstderr) ไปยัง/dev/nullหมายถึงไม่มีการพิมพ์เอาต์พุตไปยังเทอร์มินัล

โดยค่าเริ่มต้น:

stdin  ==> fd 0
stdout ==> fd 1
stderr ==> fd 2

ในสคริปต์คุณใช้> /dev/nullสาเหตุ:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> fd 2

แล้ว2>&1ทำให้:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> stdout

3
จากความเข้าใจ> /dev/null 2>&1คำสั่งนี้ส่งผลstderr ==> stdoutให้ stderr ยังคงถูกพิมพ์ไปยัง stdout ??
Weishi Zeng

11
อาจไม่สำคัญเกินไป แต่มันคือfdอะไร
kev


7
ทำไม: CMD > /dev/null 2>&1ทำงาน แต่CMD 2>&1 > /dev/nullยังให้ STDERR แก่ฉัน
dbmikus

3
แนะนำ: ใช้2>& 1ในตัวอย่างโค้ดเพื่อเน้นว่าจำนวนและเครื่องหมายแอมเปอร์แซนด์นั้นถือเป็นส่วนหนึ่งของโอเปอเรเตอร์การเปลี่ยนเส้นทาง เป็นเรื่องปกติที่การเปลี่ยนเส้นทางไปยังไฟล์เพื่อให้มีช่องว่างระหว่าง>และการ/path/to/fileเปลี่ยนเส้นทางไปยังตัวอธิบายไฟล์นั้นเป็นสิ่งเดียวกัน
Henk Langeveld

21

ฉันพยายามเข้าใจการใช้ "> / dev / null 2> & 1" ที่นี่

(โปรดทราบว่าฉันได้เพิ่มการเปลี่ยนเส้นทางมาก่อน/dev/nullในคำถามของคุณ)

ดังกล่าวข้างต้นจะเปลี่ยนเส้นทางSTDOUTและการSTDERR /dev/nullมันทำงานโดยการรวมเข้าไปในSTDERR STDOUT(โดยพื้นฐานแล้วเอาต์พุตทั้งหมดจากคำสั่งจะถูกเปลี่ยนเส้นทางไปยังอุปกรณ์ null )

... โดยไม่ทำให้สคริปต์ขัดข้อง (เช่นลองจับข้อยกเว้นในภาษาการเขียนโปรแกรม)

มันไม่เหมือนtry/catchหรืออะไร มันก็เงียบเรียงลำดับของการส่งออก (รวมถึงข้อผิดพลาด) จากคำสั่ง

เนื่องจากฉันไม่เห็นวิธีการใช้ tar ในการบีบอัดไดเรกทอรีลงในไฟล์ tar อาจทำให้เกิดข้อผิดพลาดประเภทใด ๆ

อาจทำให้เกิดข้อผิดพลาดด้วยเหตุผลหลายประการรวมถึง:

  • สิทธิ์ไม่เพียงพอในไฟล์ที่คุณพยายามจะเก็บถาวรหรือในไฟล์ที่คุณพยายามจะเขียน
  • ไม่มีพื้นที่ดิสก์เพื่อสร้างไฟล์เก็บถาวร

อธิบายอย่างดี
Aditya Gupta

7

เมื่อคุณเรียกใช้ CMD> / dev / null 2> & 1

STDOUT เปลี่ยนเส้นทางไปที่ / dev / null จากนั้น STDERR จะเปลี่ยนเส้นทางไปยัง THE ADDRESS of STDOUT ซึ่งได้รับการตั้งค่าเป็น / dev / null ดังนั้นทั้ง STDOUT และ STDERR ชี้ไปที่ / dev / null

ตรงกันข้ามเมื่อคุณเรียกใช้ CMD 2> & 1> / dev / null

STDERR เปลี่ยนเส้นทางไปยังที่อยู่ของ STDOUT (ตัวอธิบายไฟล์ 1 ในขณะนั้นหรือ / proc / self / fd / 1) จากนั้น STDOUT เปลี่ยนเส้นทางไปที่ / dev / null แต่ STDERR เปลี่ยนเส้นทางไปยัง fd1 !! เป็นผลให้เอาต์พุตปกติจาก STDOUT ถูกละทิ้ง แต่ข้อผิดพลาดที่มาจาก STDERR ยังคงถูกเขียนลงบนคอนโซล


-2

Bash I / O Redirection

แนวคิดหลักในการแก้ไขปัญหาคือ:

การเปลี่ยนเส้นทางได้ถูกนำไปใช้ตั้งแต่ RIGHT ถึง LEFT ตรงข้ามกับวิธีที่ผู้พูดภาษาอังกฤษอ่าน


ดังนั้นรหัสนี้:

command > filename 2>&1

เปลี่ยนเส้นทางstderrไปที่stdout แรก ( 2>&1) แล้วส่งstdout(รวมถึงการเปลี่ยนเส้นทางstderr) ไปที่filename( > filename) นี่คือคำอธิบาย ABSG (Ch. 20)

รหัสนี้:

command >>/dev/null 2>&1

เปลี่ยนเส้นทางstderrและstdoutไป/dev/null... ซึ่งหมายความว่าจะไม่มีที่ไหนเลย สิ่งที่ส่งไป/dev/nullจะไม่ได้รับการบันทึกไว้ในแคชหรือจำในทางใดทางหนึ่ง

พวกเขาจะถูกส่งไปที่ ' ไม่มีที่ไหนเลย ' และลืม นี่เป็นวิธีการรันโปรแกรมและทำให้แน่ใจว่าพวกเขาสร้าง NO output และจะไม่ถูกเห็นในบรรทัดคำสั่งหรือในไฟล์บันทึก


ฉันเห็นคำถามประเภทนี้เล็กน้อย ... ส่วนใหญ่เป็นเพราะฉันต้องค้นหาตัวเองตั้งแต่ฉันยังไม่ได้เข้ารหัสในปี นี่คือข้อมูลที่เป็นประโยชน์จาก ABSG:

"การเปลี่ยนเส้นทางหมายถึงการบันทึกผลลัพธ์จากไฟล์คำสั่งโปรแกรมหรือสคริปต์และส่งเป็นอินพุตไปยังไฟล์คำสั่งโปรแกรมหรือสคริปต์อื่น"

2>&1 
# Redirects stderr to stdout.

command >>filename 2>&1
# Appends both stdout and stderr
#+  to the file "filename" ...

ABSG: Advanced Bash Scripting Guide: เชื่อมโยงบทที่ 20 ข้างต้นคือการเชื่อมโยงไปยังหน้าการเปลี่ยนเส้นทางของ I / O ของโอเพนซอร์สtldp.orgเอกสารที่เรียกว่าขั้นสูงคู่มือทุบตีการเขียนสคริปต์โดยเมนเดลคูเปอร์ มันถูกระบุว่าเป็น "การสำรวจเชิงลึกของศิลปะการเขียนสคริปต์เชลล์" และฉันก็เห็นด้วยอย่างยิ่ง มันเป็นทรัพยากรที่ยอดเยี่ยมและมีคำตอบมากมายสำหรับสถานการณ์ที่บ้าคลั่งทุกประเภท

ทรัพยากรที่มีคุณค่าอื่น ๆ :มีทรัพยากรที่มีคุณค่าจำนวนมากในปัจจุบันส่วน / การบำรุงรักษาอยู่(ในรูปแบบที่มีประโยชน์หลายประการเช่น HTML, PDF, ข้อความ, ฯลฯ )บนลินุกซ์เอกสารคู่มือโครงการหน้า นี่คือบางส่วนที่ฉันพบว่ามีประโยชน์:


1
ไม่การเปลี่ยนเส้นทางได้รับการจัดการจากซ้ายไปขวา ในตัวอย่างของคุณเอาต์พุตมาตรฐานจะถูกเปลี่ยนเส้นทางไปยังfilenameข้อผิดพลาดมาตรฐานจะถูกเปลี่ยนเส้นทางไปยังที่ใดก็ตามที่เอาต์พุตมาตรฐานกำลังดำเนินการ (ไปfilename) หากเป็นไปในทางตรงกันข้ามข้อผิดพลาดมาตรฐานจะสิ้นสุดในเทอร์มินัลในขณะที่มีการเปลี่ยนเส้นทางเอาต์พุตมาตรฐานไปfilenameเท่านั้น นอกจากนี้ในcommand >file1 2>file2, file2จะไม่ถูกสร้างขึ้นถ้าfile1ไม่สามารถสร้างได้ (ไม่ว่าไม่มีfile1และfile2เป็น pathnames จริงที่แตกต่างกันโดยสิ้นเชิง)
Kusalananda
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.