2011-08-09 36 views
5

Tôi là người dùng paramiko mới và đang gặp khó khăn khi chạy các lệnh trên máy chủ từ xa với paramiko. Tôi muốn xuất một đường dẫn và cũng chạy một chương trình có tên là tophat ở chế độ nền. Tôi có thể đăng nhập tốt với paramiko.sshclient() nhưng mã của tôi để exec_command không có kết quả.basic paramiko exec_command giúp

stdin, stdout, sterr = ssh.exec_command('export PATH=$PATH:/proj/genome/programs 
/tophat-1.3.0/bin:/proj/genome/programs/cufflinks-1.0.3/bin:/proj/genome/programs/ 
bowtie-0.12.7:/proj/genome/programs/samtools-0.1.16') 

stdin, stdout, sterr = ssh.exec_command('nohup tophat -o /output/path/directory -I 
10000 -p 8 --microexon-search -r 50 /proj/genome/programs/bowtie-0.12.7/indexes 
/ce9 /input/path/1 /input/path/2 &') 

không có nohup.out tệp và python chuyển sang dòng tiếp theo không có thông báo lỗi. Tôi đã thử không có nohup và kết quả là như nhau. Tôi đang cố gắng theo dõi this paramiko tutorial.

Tôi có đang sử dụng exec_command không chính xác không?

+1

Lệnh thứ hai chạy trong một trình bao khác so với lệnh đầu tiên, vì vậy 'xuất' sẽ không có hiệu lực. –

+1

Bạn nên làm tốt hơn để chỉ đặt biến môi trường trong một dòng. Đó là: 'ssh.exec_command ('PATH =/bin:/usr/bin: etcetera nohup ...')'; điều này sẽ xuất khẩu nó cho lệnh duy nhất, đó là chính xác những gì bạn muốn. –

Trả lời

5

exec_command() không chặn và chỉ gửi lệnh tới máy chủ, sau đó Python sẽ chạy mã sau.

Tôi nghĩ bạn nên đợi lệnh thực hiện kết thúc và thực hiện công việc còn lại sau đó.

"time.sleep (10)" có thể giúp yêu cầu "thời gian nhập". Một số ví dụ cho thấy bạn có thể đọc từ đối tượng ST2out ChannelFile hoặc chỉ đơn giản là sử dụng stdout.readlines(), dường như đọc tất cả phản hồi từ máy chủ, đoán điều này có thể hữu ích.

Mã của bạn, trên 2 dòng exec_command, chúng thực sự đang chạy trong các phiên thực thi khác nhau. Tôi không chắc chắn nếu điều này có một số tác động trong trường hợp của bạn.

Tôi khuyên bạn nên xem các bản trình diễn trong thư mục trình diễn, họ đang sử dụng lớp Channel, có API tốt hơn để chặn/không chặn gửi cho cả trình bao và trình quản lý.

+0

Tôi đã có một vấn đề tương tự và tôi chỉ muốn kêu vang và nói rằng stdout.readlines() làm việc tuyệt vời cho tôi. Nó buộc kịch bản của tôi phải đợi cho đến khi lệnh exec_command() kết thúc chạy trước khi tiếp tục. Cảm ơn! – riggspc

0

Nó đang chặn tôi.

stdin, stdout, stderr = ssh.exec_command('sleep 10; hostname') 

này đợi 10 giây trước khi trở

+2

Nó chặn nếu bạn cố đọc đầu ra. – piyo

0

Bạn tốt hơn để nạp bash_profile trước khi bạn chạy lệnh của bạn. Nếu không, bạn có thể nhận được một 'lệnh không tìm thấy' ngoại lệ.

Ví dụ, tôi viết lệnh command = 'mysqldump -uu -pp -h1.1.1.1 -P999 table > table.sql' trong mục đích bán phá giá một bảng Mysql

Sau đó, tôi phải nạp bash_profile thủ công trước khi có lệnh bán phá giá bằng cách gõ . ~/.profile; .~/.bash_profile;.

Ví dụ

my_command = 'mysqldump -uu -pp -h1.1.1.1 -P999 table > table.sql;' 

pre_command = """ 
. ~/.profile; 
. ~/.bash_profile; 
""" 

command = pre_command + my_command 

stdin, stdout, stderr = ssh.exec_command(command) 
1

Tôi cũng chạy vào cùng một vấn đề và sau khi xem xét this articlethis answer, tôi thấy giải pháp là để gọi phương thức recv_exit_status() của Channel. Đây là mã của tôi:

import paramiko; 
import time; 

cli = paramiko.client.SSHClient(); 
cli.set_missing_host_key_policy(paramiko.client.AutoAddPolicy()); 
cli.connect(hostname="10.66.171.100", username="mapping"); 
stdin_, stdout_, stderr_ = cli.exec_command("ls -l ~"); 
# time.sleep(2); # Previously, I had to sleep for some time. 
stdout_.channel.recv_exit_status(); 
lines = stdout_.readlines(); 
for line in lines: 
    print line; 

cli.close(); 

Bây giờ mã của tôi sẽ bị chặn cho đến khi lệnh từ xa kết thúc. Phương pháp này được giải thích here và vui lòng chú ý đến cảnh báo.