kết hợp đầu ra từ hai lệnh trong bash


81

Có thể kết hợp đầu ra từ hai lệnh này?

node ~/projects/trunk/index.js 
python ~/projects/trunk/run.py run

Không có lệnh nào thoát ra nên tôi không biết phải làm thế nào.


3
Nếu các chương trình không hoàn thành, có lẽ họ viết đầu ra liên tục? Bạn muốn làm gì với đầu ra của họ? Các đường xen kẽ, ...? tại sao bạn muốn làm việc này?
vonbrand

2
Lệnh nút không xuất ra nhiều, nhưng nó vẫn cần chạy. Con trăn đầu ra tất cả các yêu cầu, tôi muốn chụp cả hai và xem cả hai trong cùng một cửa sổ shell.
chovy

Câu trả lời:


108

Bạn có thể kết hợp hai lệnh bằng cách nhóm nó với { }:

{ command1 & command2; }

cho đến nay, bạn có thể chuyển hướng nhóm đến một tệp (cuối cùng ;trước đó }là bắt buộc):

{ command1 & command2; } > new_file

nếu bạn muốn tách STDOUTSTDERRtrong hai tệp:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
Không quan trọng là chương trình họ không hoàn thành. 'tail -f' cũng không "kết thúc", nhưng điều này vẫn hoạt động và kết hợp các đầu ra của cả hai chương trình. Hoạt động cho nhiều hơn hai lệnh là tốt. ^ c để thoát chỉ giết một trong các lệnh được nhóm. Tuy nhiên, bạn sẽ phải giết người khác bằng tay.
SuperMagic

5
Có vẻ như bạn thiếu lần cuối ;trước }, điều đó là bắt buộc!
Gilles Quenot

2
Được cảnh báo: Điều này không bảo tồn toàn bộ dòng! Bạn sẽ nhận được kết quả đầu ra không đáng tin cậy khi các dòng được tách ra một phần và trộn lẫn với nhau. Bạn có thể thử điều này với { yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'lý tưởng là không in bất cứ điều gì nếu dòng không bị hỏng.
antak

8
Tôi thà sử dụng &&thay vì &! command1 & command2- điều này chạy lệnh1 trong nền và bắt đầu lệnh2 ngay lập tức, do đó chạy cả hai lệnh song song và làm rối đầu ra. command1 && command2- cái này chạy lệnh1 (ở nền trước) và sau đó, nếu lệnh1 bị ép, chạy lệnh2.
DUzun

1
@DUzun OP cho biết không có lệnh nào thoát, vì vậy với giải pháp của bạn, lệnh thứ hai sẽ không bao giờ chạy
Zoey Hewll

50

Tổng quát hơn, có thể sử dụng nhóm con hoặc nhóm lệnh và chuyển hướng đầu ra của cả nhóm cùng một lúc.

Mã số:

( command1 ; command2 ; command3 ) | cat

{ command1 ; command2 ; command3 ; } > outfile.txt

Sự khác biệt chính giữa hai cái là cái thứ nhất tách ra của một tiến trình con, trong khi cái thứ hai hoạt động trong bối cảnh của shell chính. Điều này có thể có hậu quả liên quan đến việc thiết lập và sử dụng các biến và các cài đặt môi trường khác, cũng như hiệu suất.

Đừng quên rằng khung đóng trong nhóm lệnh (và các hàm) phải được tách biệt khỏi nội dung bằng dấu chấm phẩy hoặc dòng mới. Điều này là do "}"thực sự là một lệnh (từ khóa) của riêng nó và phải được xử lý như một lệnh.


2
Chuyển hướng từ ( )hoạt động tốt quá.
muru

2
}không phải là một lệnh ở tất cả. Đó là một từ dành riêng. Cùng đi cho {. Tôi thường viết những danh sách như vậy : { command1;command2;} > outfile.txt. Bạn có thể thêm dấu cách sau dấu chấm phẩy nhưng không cần thiết. Không gian sau { cần thiết, mặc dù.
tự đại diện

1
Được cảnh báo: Điều này không bảo tồn toàn bộ dòng! Bạn sẽ nhận được kết quả đầu ra không đáng tin cậy khi các dòng được tách ra một phần và trộn lẫn với nhau. Bạn có thể thử điều này với ( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'lý tưởng là không in bất cứ điều gì nếu dòng không bị hỏng. (H / t đến @antak).
Ole Tange

3
Đôi khi bạn chỉ muốn chạy ( command1 && command2 && command3 ) | cat
lệnh2 nếu lệnh1 không hoạt động

Tôi thích dấu ngoặc tròn ()như với dấu ngoặc nhọn, {}nó chạy như một tiến trình nền và sau đó bạn phải xử lý kết quả đầu ra từ đó. Cũng ống cho mèo `| cat` là một thay thế đẹp hơn sau đó `> / dev / stdout`
DarkMukke

2

Tôi đã kết thúc việc này, các đề xuất khác không hoạt động, vì lệnh thứ 2 hoặc bị giết hoặc không bao giờ được thực thi.

alias app () {
    nohup python ~/projects/trunk/run.py run 1>/tmp/log 2>&1 &
    echo $! > /tmp/api.pid
    nohup node ~/projects/trunk/index.js 1>/tmp/log 2>&1 &
    echo $! > /tmp/client.pid
    tail -f /tmp/log
}

1
Lưu ý: điều này có thể gây ra lỗi I / O nếu hai quá trình cố gắng ghi vào tệp "cùng một lúc".
Djizeus

2
có thể chỉ định 2 tệp nhật ký khác nhau và thực hiện tail -f *.logmặc dù tôi chưa bao giờ thấy đây là sự cố với 2 quy trình khác nhau ghi vào cùng một tệp nhật ký.
chovy

@chovy: bạn có thể viết vấn đề của bạn như câu hỏi ở đây không ... nó rất hữu ích
Abdennour TOUMI

1
Được cảnh báo: Điều này không bảo tồn toàn bộ dòng! Bạn sẽ nhận được kết quả đầu ra không đáng tin cậy khi các dòng được tách ra một phần và trộn lẫn với nhau. Bạn có thể thử điều này với lệnh1 = yes {1..20}lệnh2 = yes {1..20}và dẫn đầu ra kết hợp qua | grep -v '^1 2 3'đó lý tưởng là không in bất cứ thứ gì nếu dòng không bị hỏng. (H / t đến @antak).
Ole Tange

Trên hết, đĩa của bạn có thể chạy đầy nếu lượng dữ liệu lớn.
Ole Tange

2

Thử đi:

paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile

1
'dán' làm gì?
chovy

@chovy, xem tại đây: techrepublic.com/article/ Từ Không chắc chắn liệu nó có hoạt động trong bối cảnh này hay không.
FixMaker

Tôi không nghĩ rằng dán là thích hợp ở đây, vì nó có nghĩa là đặt các cột bên cạnh nhau
Bernhard

@Bernhard thực sự. Nhưng nó không được chỉ định trong req's
ếchstarr78

@ Frogstarr78 Tôi nghĩ rất khó có khả năng đây là điều anh ấy muốn, nhưng bạn nói đúng, nó không được chỉ định.
Bernhard

1

Hầu hết các giải pháp cho đến nay xử lý tồi với vấn đề một phần dòng. Giả sử trong một giây rằng các chương trình là:

cmd1() {
    perl -e 'while(1) { print "a"x3000_000,"\n"}'
}
export -f cmd1
cmd2() {
    perl -e 'while(1) { print "b"x3000_000,"\n"}'
}
export -f cmd2

Khi chạy song song bạn muốn đầu ra có đầy đủ các dòng as theo sau là các dòng bs đầy đủ . Những gì bạn không muốn là as và bs trộn trên cùng một dòng ( tr -s abthay thế lặp lại as bằng một lần duy nhất a, vì vậy sẽ dễ dàng hơn để xem điều gì xảy ra):

# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab

Thay vào đó, nếu bạn sử dụng GNU Parallel, bạn sẽ có được các dòng đầy đủ sạch với as hoặc bs nhưng không bao giờ bị trộn lẫn:

$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a

Các phiên bản mới hơn của GNU Parallel thậm chí còn tránh làm đầy đĩa của bạn: Phần trên có thể chạy mãi mãi.


0

Vì bạn đã sử dụng node, bạn có thể muốn thử đồng thời

Chạy nhiều lệnh đồng thời. Thích npm run watch-js & npm run watch-lessnhưng tốt hơn.


0

Đối với trường hợp đặc biệt là kết hợp nhiều đầu ra lệnh BASH vào một dòng, đây là công thức để lần lượt chạy từng lệnh, loại bỏ bất kỳ dòng mới nào giữa các đầu ra của chúng.

(echo 'ab' && echo 'cd' && echo 'ef') | tr -d '\n'
>>> abcdef

Như một ví dụ trong thế giới thực, mã bên dưới sẽ nhúng một thông điệp ASCII giữa hai chuỗi byte cố định (tạo thành một lệnh in, trong trường hợp này)

#   hex prefix           encode a message as hex    hex suffix    | strip newline | hex to binary | (then, for example, send the binary over a TCP connection)
(echo '1b40' && echo "Test print #1" | xxd -p && echo '1d564103') | tr -d '\n'    | xxd -r -p     | nc -N 192.168.192.168 9100

(Lưu ý: phương pháp này chỉ hoạt động nếu lệnh thoát. Để kết hợp thiết bị xuất chuẩn từ các lệnh không thoát, hãy xem các câu trả lời khác.)


(1) Vui lòng hiển thị đầu ra (dự kiến) của lệnh thứ hai của bạn. (2) Hãy cho biết OP sẽ sử dụng kỹ thuật này như thế nào để giải quyết vấn đề của mình.
Scott

1) Đầu ra của lệnh thứ hai là nhị phân không phải ascii, vì vậy sẽ không hữu ích khi hiển thị nó. 2) OP có khả năng giải quyết vấn đề cụ thể của anh ấy từ năm 2013 đến nay. Câu hỏi này bây giờ thực sự là một tài liệu tham khảo về việc kết hợp các thiết bị xuất chuẩn của nhiều lệnh Bash, vì vậy tôi tin rằng một kỹ thuật kết hợp chúng trên một dòng là một "công thức" hữu ích được đề cập ở đây (vì tôi đến đây để tìm nó và không thể tìm thấy nó).
Lu-ca
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.