Tại sao GNU không hoạt động song song với bash -cv?


9
% echo -e '1\n2' | parallel "bash -c 'echo :\$1' '' {}"
:1
:2
% echo -e '1\n2' | parallel bash -c 'echo :\$1' '' {}


%

Tôi hy vọng dòng thứ hai sẽ hành động tương tự.

Câu trả lời:


11

parallelđã chạy lệnh trong shell đã được xác định (shell nào được xác định bằng parallelcách sử dụng heuristic (ý định gọi shell tương tự như shell parallelđược gọi từ đó ). Bạn có thể đặt $PARALLEL_SHELLbiến để sửa shell).

Đây không phải là một lệnh mà bạn chuyển đến parallelgiống như bạn sẽ làm cho lệnh envhoặc xargslệnh, mà là một dòng lệnh shell (giống như bạn thực hiện cho evallệnh).

Giống như cho eval, trong parallel arg1 arg2, parallellà nối các đối số đó với khoảng trắng ở giữa (vì vậy nó trở thành arg1 arg2) và chuỗi đó được truyền vào <the-shell> -c.

Đối với các đối số được truyền trên parallelstdin, hãy paralleltrích dẫn chúng theo định dạng được mong đợi bởi lớp vỏ cụ thể đó (một nhiệm vụ dễ bị lỗi và khó hiểu, đó là lý do tại sao bạn sẽ thấy có rất nhiều lỗi được khắc phục xung quanh đó trong parallelChangelog ( một số vẫn chưa được sửa chữa kể từ 2017 / 03-06)) và thêm nó vào dòng lệnh đó.

Vì vậy, ví dụ, nếu được gọi từ bên trong bash,

echo "foo'bar" | parallel echo foo

Sẽ có cuộc gọi song song bash -cvới echo foo foo\'barnhư là dòng lệnh. Và nếu được gọi từ bên trong rc(hoặc với PARALLEL_SHELL=rc) rc -cvới echo foo foo''''bar.

Trong của bạn:

parallel bash -c 'echo :\$1' '' {}

parallel nối các đối số đó đưa ra:

bash -c echo :$1  {}

Và với sự {}mở rộng và được trích dẫn trong các định dạng phù hợp với vỏ bạn đang gọi điện thoại paralleltừ, qua đó để <that-shell> -cmà sẽ gọi bash -c echovới :$1trong $0và lập luận hiện tại $1.

Đó không phải là cách làm parallelviệc. Ở đây, bạn có thể muốn:

printf '1\n2\n' | PARALLEL_SHELL=bash parallel 'echo :{}'

Để xem những gì parallelhiện, bạn có thể chạy nó bên dưới strace -fe execve(hoặc tương đương trên hệ thống của bạn nếu không phải là Linux).

Tại đây, bạn có thể sử dụng GNU xargsthay vì parallelxử lý đơn giản hơn gần với những gì bạn mong đợi:

printf '1\n2\n' | xargs -rn1 -P4 bash -c 'echo ":$1"' ''

Xem thêm cuộc thảo luận tại https://lists.gnu.org/archive/html/orms-abul/2015-05/msg00005.html

Lưu ý rằng bash -c 'echo foo' '' foo, bạn đang tạo $0chuỗi trống cho tập lệnh nội tuyến đó. Tôi sẽ tránh điều đó vì nó $0cũng được sử dụng trong các thông báo lỗi. Đối chiếu:

$ bash -c 'echo x > "$1"' '' /
: /: Is a directory

với.

$ bash -c 'echo x > "$1"' bash /
bash: /: Is a directory

Cũng lưu ý rằng việc để các biến không được trích dẫn có ý nghĩa rất đặc biệt bashechothường không thể được sử dụng cho dữ liệu tùy ý.


4
Môn diều! Đây là một câu trả lời tốt hơn so với tác giả của GNU Parallel có thể đã viết.
Ole Tange
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.