วิธีการเปลี่ยนเส้นทางและผนวกทั้ง stdout และ stderr ไปยังไฟล์ด้วย Bash?


1533

เพื่อเปลี่ยนเส้นทางstdoutไปยังไฟล์ที่ถูกตัดทอนใน Bash ฉันรู้ว่าจะใช้:

cmd > file.txt

หากต้องการเปลี่ยนเส้นทางstdoutใน Bash ต่อท้ายไฟล์ฉันรู้ที่จะใช้:

cmd >> file.txt

เพื่อเปลี่ยนเส้นทางทั้งstdoutและstderrไปยังไฟล์ที่ถูกตัดทอนฉันรู้ว่าจะใช้:

cmd &> file.txt

ฉันจะเปลี่ยนเส้นทางทั้งstdoutและstderrต่อท้ายไฟล์ได้อย่างไร cmd &>> file.txtไม่ได้ผลสำหรับฉัน


37
ฉันต้องการทราบว่า &> outfile เป็นรหัสเฉพาะของ Bash (และอื่น ๆ ) ไม่ใช่แบบพกพา วิธีที่จะพกพาได้ (คล้ายกับคำตอบที่ต่อท้าย) อยู่เสมอและยังคงเป็น> outfile 2> & 1
TheBonsai

คำตอบ:


1997
cmd >>file.txt 2>&1

Bash จะทำการเปลี่ยนเส้นทางจากซ้ายไปขวาดังนี้:

  1. >>file.txt: เปิดfile.txtในโหมดผนวกและเปลี่ยนเส้นทางที่stdoutนั่น
  2. 2>&1: การเปลี่ยนเส้นทางstderrไปยัง"ที่stdoutกำลังเกิด" ในกรณีนี้นั่นคือไฟล์ที่เปิดในโหมดผนวก กล่าวอีกนัยหนึ่ง&1reuse ตัวอธิบายไฟล์ซึ่งstdoutปัจจุบันใช้

33
ใช้งานได้ดี! แต่มีวิธีที่จะทำให้ความรู้สึกของเรื่องนี้หรือฉันควรจะปฏิบัติเช่นนี้สร้างปรมาณูทุบตี?
flybywire

181
มันเป็นการเปลี่ยนเส้นทางที่ง่ายงบการเปลี่ยนเส้นทางจะถูกประเมินเช่นเคยจากซ้ายไปขวา >> ไฟล์: แดง STDOUT ไปยังไฟล์ (โหมดต่อท้าย) (ย่อมาจาก 1 >> ไฟล์) 2> & 1: สีแดง STDERR ไปที่ "ตำแหน่ง stdout ไป" โปรดทราบว่าการแปลความหมาย "เปลี่ยนเส้นทาง STDERR ไปยัง STDOUT" ผิด
TheBonsai

31
มันบอกว่า "ผนวกเอาท์พุท (stdout, file descriptor 1) ไปยัง file.txt และส่ง stderr (file descriptor 2) ไปยังตำแหน่งเดียวกับ fd1"
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

2
@TheBawai จะทำอย่างไรถ้าฉันต้องการเปลี่ยนเส้นทาง STDERR ไปยังไฟล์อื่น แต่ต่อท้าย? เป็นไปได้ไหม
arod

41
ถ้าคุณทำcmd >>file1 2>>file2มันควรจะบรรลุสิ่งที่คุณต้องการ
Woodrow Douglass

367

มีสองวิธีในการทำเช่นนี้ขึ้นอยู่กับรุ่น Bash ของคุณ

วิธีคลาสสิคและพกพา ( Bash pre-4 ) คือ:

cmd >> outfile 2>&1

วิธีที่ไม่สามารถพกพาได้เริ่มต้นด้วยBash 4คือ

cmd &>> outfile

(คล้ายกับ&> outfile)

สำหรับรูปแบบการเข้ารหัสที่ดีคุณควร

  • ตัดสินใจว่าการพกพาเป็นเรื่องที่น่ากังวลหรือไม่ (จากนั้นใช้วิธีแบบดั้งเดิม)
  • ตัดสินใจว่าการพกพาที่ใช้กับ Bash pre-4 นั้นเป็นเรื่องที่น่ากังวลหรือไม่
  • ไม่ว่าคุณจะใช้ไวยากรณ์รูปแบบใดไม่เปลี่ยนในสคริปต์เดียวกัน (สับสน!)

หากสคริปต์ของคุณเริ่มต้นด้วย#!/bin/sh(ไม่ว่าจะตั้งใจหรือไม่ก็ตาม) ดังนั้นโซลูชัน Bash 4 และโดยทั่วไปแล้วรหัสเฉพาะของ Bash นั้นไม่ใช่วิธีที่จะไป

โปรดจำไว้ว่า Bash 4 &>>เป็นเพียงไวยากรณ์ที่สั้นกว่า - ไม่แนะนำการทำงานใหม่หรืออะไรทำนองนั้น

ไวยากรณ์คือ (ข้างๆไวยากรณ์การเปลี่ยนเส้นทางอื่น ๆ ) ที่อธิบายไว้ที่นี่: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
ฉันชอบ & >> เพราะมันสอดคล้องกับ &> และ >> นอกจากนี้ยังง่ายต่อการอ่าน 'ผนวกเอาต์พุตและข้อผิดพลาดในไฟล์นี้' กว่า 'ส่งข้อผิดพลาดไปยังเอาต์พุตต่อท้ายเอาต์พุตไปยังไฟล์นี้' หมายเหตุขณะที่ลีนุกซ์โดยทั่วไปมี bash เวอร์ชันปัจจุบัน, OS X, ณ เวลาที่เขียน, ยังคงต้องใช้ bash 4 เพื่อติดตั้งด้วยตนเองผ่าน homebrew เป็นต้น
mikemaccana

ฉันชอบมากกว่านี้เพราะมันสั้นกว่าและมีเพียง tweoi ที่ต่อบรรทัดดังนั้นตัวอย่างเช่น zsh ที่ทำจาก "& >>"
Phillipp

สิ่งสำคัญที่ควรทราบคือในงาน cron คุณต้องใช้ไวยากรณ์ pre-4 แม้ว่าระบบของคุณจะมี Bash 4
hyperknot

5
@zsero cron ไม่ได้ใช้ทุบตีเลย ... shมันใช้ คุณสามารถเปลี่ยนเปลือกเริ่มต้นได้ด้วยการSHELL=/bin/bashต่อท้ายcrontab -eไฟล์
เรย์ฟอสส์

89

ใน Bash คุณสามารถระบุการเปลี่ยนเส้นทางของคุณไปยังไฟล์ต่างๆอย่างชัดเจน:

cmd >log.out 2>log_error.out

การต่อท้ายจะเป็น:

cmd >>log.out 2>>log_error.out

6
การเปลี่ยนเส้นทางสองสตรีมไปยังไฟล์เดียวกันโดยใช้ตัวเลือกแรกของคุณจะทำให้อันแรกเขียน "ด้านบน" ของวินาทีการเขียนทับเนื้อหาบางส่วนหรือทั้งหมด ใช้cmd >> log.out 2> log.outแทน
Orestis P.

3
ขอบคุณสำหรับการจับที่; คุณพูดถูกใครจะขัดขวางคนอื่น อย่างไรก็ตามคำสั่งของคุณไม่ทำงานเช่นกัน cmd >log.out 2>&1ผมคิดว่าวิธีเดียวที่จะเขียนไปยังแฟ้มเดียวกันตามที่ได้รับก่อน ฉันกำลังแก้ไขคำตอบเพื่อลบตัวอย่างแรก
Aaron R.

65

ใน Bash 4 (เช่นเดียวกับ ZSH 4.3.11):

cmd &>>outfile

เพิ่งออกจากกล่อง


2
@ ทั้งหมด: นี่เป็นคำตอบที่ดีเพราะมันใช้ได้กับ bash และสั้นดังนั้นฉันได้แก้ไขเพื่อให้แน่ใจว่ามันกล่าวถึง bash อย่างชัดเจน
mikemaccana

10
@mikemaccana: คำตอบของ TheBonsaiแสดง bash 4 solution ตั้งแต่ปี 2009
jfs

52

สิ่งนี้จะทำงานได้ดี:

your_command 2>&1 | tee -a file.txt

มันจะเก็บบันทึกทั้งหมดในfile.txtรวมทั้งทิ้งไว้ใน terminal


นี่คือคำตอบที่ถูกต้องหากคุณต้องการเห็นผลลัพธ์ในเครื่องเช่นกัน อย่างไรก็ตามนี่ไม่ใช่คำถามแรกที่ถาม
Mikko Rantalainen

25

ลองสิ่งนี้

You_command 1>output.log  2>&1

การใช้ &> x.file ของคุณใช้งานได้ใน bash4 ขอโทษสำหรับสิ่งนั้น : (

นี่คือเคล็ดลับเพิ่มเติมมา

0, 1, 2 ... 9 เป็นตัวอธิบายไฟล์ใน bash

0 หมายถึงstdin1 ยืนสำหรับstdout2 stderrorยืน 3 ~ 9 มีไว้สำหรับการใช้งานชั่วคราวอื่น ๆ

ไฟล์ descriptor ใด ๆ สามารถเปลี่ยนเส้นทางไปยัง file descriptor หรือไฟล์อื่น ๆ โดยใช้โอเปอเรเตอร์>หรือ>>(ต่อท้าย)

การใช้งาน: < file_descriptor > > < ชื่อไฟล์ | & file_descriptor >

โปรดอ้างอิงถึงhttp://www.tldp.org/LDP/abs/html/io-redirection.html


ตัวอย่างเช่นคุณจะทำอะไรบางอย่างที่แตกต่างกันกว่า OP ถาม: มันจะเปลี่ยนเส้นทาง stderr ของYou_commandที่ stdout และ stdout ของไปยังแฟ้มYou_command output.logนอกจากนี้มันจะไม่ผนวกเข้ากับไฟล์ แต่จะเขียนทับมัน
pabouk

ถูกต้อง: ตัวอธิบายไฟล์อาจเป็นค่าใด ๆ ที่มากกว่า 3 สำหรับไฟล์อื่นทั้งหมด
Itachi

5
คำตอบของคุณแสดงข้อผิดพลาดทั่วไปในการเปลี่ยนเส้นทางเอาต์พุต: การเปลี่ยนเส้นทาง STDERR ไปยังที่ STDOUT กำลังชี้และหลังจากนั้นเปลี่ยนเส้นทาง STDOUT ไปยังไฟล์ สิ่งนี้จะไม่ทำให้ STDERR ถูกเปลี่ยนเส้นทางไปยังไฟล์เดียวกัน ลำดับการเปลี่ยนเส้นทางสำคัญ
Jan Wikholm

1
หมายความว่าฉันควรเปลี่ยนเส้นทาง STDERROR ไปที่ STDOUT ก่อนจากนั้นเปลี่ยนเส้นทาง STDOUT เป็นไฟล์ 1 > output.log 2>&1
Quintus.Zhou

1
@ Quintus.Zhou Yup เวอร์ชันของคุณเปลี่ยนเส้นทางไปยังผิดพลาดและในเวลาเดียวกันก็สามารถจัดไฟล์ได้
Alex Yaroshevich

11

ฉันประหลาดใจที่เกือบสิบปีที่ผ่านมายังไม่มีใครโพสต์วิธีการนี้:

หากใช้ bash รุ่นเก่ากว่าที่&>>ไม่มีให้ใช้งานคุณสามารถทำสิ่งต่อไปนี้ได้

(cmd 2>&1) >> file.txt

spawns นี้ subshell ดังนั้นจึงมีประสิทธิภาพน้อยกว่าวิธีการแบบดั้งเดิมของcmd >> file.txt 2>&1และมันจึงจะไม่ทำงานสำหรับคำสั่งที่จำเป็นต้องปรับเปลี่ยนเปลือกปัจจุบัน (เช่นcd, pushd) แต่วิธีการนี้ให้ความรู้สึกเป็นธรรมชาติมากขึ้นและเข้าใจกับฉัน:

  1. เปลี่ยนเส้นทาง stderr ไปยัง stdout
  2. เปลี่ยนเส้นทาง stdout ใหม่โดยการต่อท้ายไฟล์

นอกจากนี้วงเล็บยังลบความกำกวมของคำสั่งโดยเฉพาะอย่างยิ่งถ้าคุณต้องการไพพ์ stdout และ stderr ไปยังคำสั่งอื่นแทน


การใช้งานนี้ทำให้เกิดกระบวนการพิเศษหนึ่งกระบวนการสำหรับระบบที่จะเรียกใช้ การใช้ไวยากรณ์cmd >> file 2>&1ทำงานได้ในทุกเชลล์และไม่จำเป็นต้องมีกระบวนการพิเศษในการรัน
Mikko Rantalainen

@MikkoRantalainen ฉันได้อธิบายแล้วว่ามันวางไข่ subshell และมีประสิทธิภาพน้อยกว่า ประเด็นของวิธีนี้คือถ้าประสิทธิภาพไม่ใช่เรื่องใหญ่ (และไม่ค่อยมี) วิธีนี้ง่ายต่อการจดจำและยากที่จะผิด
jamesdlin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.