2015-01-08 13 views
6

kịch bản của tôi làm việc nếu tôi chạy nó một cách tương tác trên vỏ lệnh:GNU Parallel trong kịch bản BASH với "xuất khẩu -f <func>" thất bại với "Command Not Found" lỗi khi Crond

$ cat ndmpcopy_cron_parallel_svlinf05.bash 
#!/usr/software/bin/bash 

ndmpcopy_cron_parallel() { 

timestamp=`date +%Y%m%d-%H%M` 
LOG=/x/eng/itarchives/ndmpcopylogs/05_$1/ndmpcopy_status 
TSLOG=${LOG}_$timestamp 

src_filer='svlinf05' 
src_account='ndmp' 
src_passwd='src_passwd' 
dst_svm='svlinfsrc' 
dst_account='vsadmin-backup' 
dst_passwd='dst_passwd' 

host=`hostname` 
echo $host 

ssh -l root $src_filer "priv set -q diag ; ndmpcopy -sa $src_account:$src_passwd -da $dst_account:$dst_passwd -i $src_filer.eng.netapp.com:/vol/$1 10.56.10.161:/$dst_svm/$1" | tee -a $TSLOG 

echo "ndmpcopy Completed: `date` " 

} 

export -f ndmpcopy_cron_parallel 

/u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local 

Tuy nhiên, kịch bản thất bại và phàn nàn chức năng xuất khẩu, ndmpcopy_cron_parallel, không thể được tìm thấy:

$ crontab -l 

40 0,2,4,6,8,10,12,14,16,18,20,22 * * * /u/jsung/bin/ndmpcopy_cron_parallel_svlinf05.bash 

Lỗi:

Subject: Cron <[email protected]> /u/jsung/bin/ndmpcopy_cron_parallel_svlinf05.bash 


Computers/CPU cores/Max jobs to run 
1:local/2/1 

Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete 
ETA: 0s Left: 1 AVG: 0.00s local:1/0/100%/0.0s **/bin/bash: ndmpcopy_cron_parallel: command not found** 
ETA: 0s Left: 0 AVG: 0.00s local:0/1/100%/0.0s 

Tôi đã được tìm kiếm xung quanh và thử những thứ khác nhau trong một thời gian. Tôi thậm chí còn chỉnh sửa $ PATH. Không chắc tôi đã bỏ lỡ điều gì. Chúng ta có thể nhúng GNU Parallel vào BASH script và đặt vào crontab không?

+0

thế nào là '/ bin/bash' khác '/ usr/software/bin/bash'? Công việc cron dường như đang sử dụng '/ bin/bash'. Tập lệnh của bạn có hoạt động khi chạy với '/ bin/bash' không? –

+0

Phải. Không có nhiều khác biệt./usr/software/bin là nơi công ty chúng tôi lưu trữ các tiện ích./bin/bash là vị trí mặc định với máy chủ. $/bin/bash --version GNU bash, phiên bản 4.1.2 (1) -release (x86_64-redhat-linux-gnu) Bản quyền (C) 2009 Free Software Foundation, Inc. Giấy phép GPLv3 +: GNU GPL phiên bản 3 hoặc mới hơn $/usr/software/bin/bash --version GNU bash, phiên bản 4.2.53 (1) -release (x86_64-unknown -linux-gnu) Bản quyền (C) 2011 Free Software Foundation, Inc. Giấy phép GPLv3 +: GNU GPL phiên bản 3 hoặc mới hơn jsung8

+0

Và bạn có thể chạy tập lệnh của mình với '/ bin/bash' theo cách thủ công? (Nó có vẻ như nó nên làm việc offhand.) Tôi không quen thuộc với 'song song' bạn có thể nhận được nó để chạy một kịch bản (và đặt chức năng đó trong một kịch bản) thay vì phương pháp này env? –

Trả lời

7

Xin chúc mừng. Bạn đã từng là shell-shocked.

Bạn đã hai phiên bản của bash được cài đặt trên hệ thống của bạn:

  • /bin/bash v4.1.2 Một bash chưa được vá cũ
  • /usr/phần mềm/bin/bash v4.2.53 Một trung niên bash, được vá chống lại Shellshock

Số cuối cùng trong phiên bản bash triple là cấp bản vá. Lỗi Shellshock liên quan đến một số bản vá lỗi, nhưng lỗi có liên quan là 4.1.14, 4.2.50 và 4.3.27. Bản vá đó thay đổi định dạng của các hàm đã xuất, với hệ quả là:

  • Nếu bạn xuất một hàm từ bash trước vỏ sò sang bash sau vỏ sò, bạn sẽ thấy cảnh báo và hàm đã xuất sẽ bị từ chối .
  • Nếu bạn xuất một hàm từ bash sau vỏ sò sang bash trước shellshock, định dạng xuất chức năng sẽ không được nhận dạng để nó sẽ bị bỏ qua âm thầm.

Trong cả hai trường hợp, chức năng sẽ không được xuất. Nói cách khác, bạn chỉ có thể xuất một hàm giữa hai phiên bản bash nếu chúng có cả shellshock patched, hoặc nếu không có shellshock patched.

Kịch bản của bạn cho biết rõ ràng bash nào sẽ sử dụng để chạy: phần trong/usr/software/bin/bash, đã được vá. Kịch bản lệnh gọi GNU song song, và GNU song song sau đó phải khởi động một hoặc nhiều subshells để chạy các lệnh. GNU song song sử dụng giá trị của biến môi trường SHELL để tìm trình bao mà nó nên sử dụng.

Tôi cho rằng trong môi trường lệnh shell dùng của bạn, SHELL được thiết lập để /usr/software/bin/bash, và rằng trong môi trường mà cron thực thi, nó được thiết lập để /bin/bash. Nếu trường hợp đó xảy ra, bạn sẽ không gặp vấn đề khi xuất hàm khi bạn thử nó từ dấu nhắc bash, nhưng trong môi trường cron, bạn sẽ kết thúc cố gắng xuất hàm từ bash sau shellshock sang bash trước shellshock, và như được mô tả ở trên kết quả là việc xuất sẽ bị bỏ qua âm thầm. Do đó lỗi.

Để khắc phục sự cố, bạn cần đảm bảo rằng bạn sử dụng bash được sử dụng để chạy tập lệnh cũng giống như bash được sử dụng bởi GNU song song. Ví dụ, bạn có thể thiết lập rõ ràng shell trước khi gọi GNU song song.

export SHELL=/usr/software/bin/bash 
# ... 
/u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local 

Hoặc bạn chỉ có thể thiết lập nó cho lệnh song song bản thân:

SHELL=/usr/software/bin/bash /u/jsung/bin/parallel -j 0 --wd . --env ndmpcopy_cron_parallel --eta ndmpcopy_cron_parallel ::: local 
+0

rick và Ole, Cảm ơn rất nhiều vì sự thấu hiểu của bạn! shellshock thực sự là nguyên nhân gốc rễ. Rất cảm kích!! Bí quyết duy nhất tôi đã tìm ra là shellshock "/ bin/bash" thực sự được kích hoạt bởi crontab. Công việc cron cuối cùng đã khởi động sau khi tôi thêm SHELL và PATH vào crontab của tôi. Tôi nghĩ rằng SHELL được yêu cầu trong kịch bản nếu chúng tôi phân phối tác phẩm trên máy chủ từ xa. Để mang lại lợi ích cho người khác, tôi tóm tắt những thay đổi quan trọng mà tôi đã thực hiện đối với tập lệnh và crontab trong nhận xét tiếp theo – jsung8

+0

Thay đổi trong tập lệnh của tôi: xuất SHELL =/usr/software/bin/bash xuất -f ndmpcopy_cron_parallel /u/jsung/bin/song song -j 0 --env SHELL --eta ndmpcopy_cron_parallel ::: local Thay đổi trên crontab: SHELL =/usr/software/bin/bash PATH =/usr/software/bin:/u/jsung/bin – jsung8

2

Là rici nói, vấn đề là có thể do shellshock. Shellshock không ảnh hưởng đến GNU Parallel, nhưng các bản vá lỗi để sửa shellshock đã phá vỡ việc chuyển các hàm bằng cách sử dụng '--env'.

GNU Song song đang bắt kịp với các bản vá vỏ sò trong Bash: Bash đã sử dụng BASH_FUNC_myfunc() làm tên biến cho chức năng xuất, nhưng các phiên bản gần đây sử dụng BASH_FUNC_myfunc%%. Vì vậy, GNU Parallel cần biết điều này khi chuyển một hàm.

Phiên bản '()' được sửa trong 20141022 và phiên bản '%%' dự kiến ​​sẽ được khắc phục trong 20150122. Chúng sẽ hoạt động trong bất kỳ kết hợp nào. Vì vậy, Bash từ xa của bạn không cần phải được vá theo cùng một cách như Bash cục bộ của bạn: GNU Parallel sẽ "làm điều đúng", và không cần phải thay đổi mã của riêng bạn.

Bạn nên cảm thấy tự do để kiểm tra phiên bản git trong đó cả hai đều cố định: git clone git: //git.savannah.gnu.org/parallel.git

+0

Ole, Cảm ơn lời khuyên của bạn về --env vì vậy tôi đã sử dụng "--env SHELL" để liên kết SHELL environ var với song song ... – jsung8