#python #c #python-3.x #ssh #paramiko
Вопрос:
Привет, я пытаюсь создать функцию, которая удаленно выполняет мой сценарий обнюхивания пакетов на моем raspberry pi, используя paramiko и ssh.
def startPacketReceiver():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(RECV_IP_ADDRESS, username="pi", password="raspberry")
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("sudo gcc Code/test.c amp;amp; sudo ./a.out")
print("Done")
Файл test.c — это сценарий поиска пакетов. Он завершится только с помощью CTRL-C (или эквивалентного метода). Это не заканчивается естественным/в конечном итоге.
Я хочу иметь возможность запустить приемник, а затем выйти из приемника, например:
startPacketReceiver()
...
stopPacketReceiver()
В настоящее время, когда я запускаю скрипт python, я никогда не получаю сообщение о печати «Готово», что означает, что программа зависает на exec_command и не будет продолжаться до тех пор, пока она не будет завершена.
Дополнительная информация
Файл test.c циклически повторяется бесконечно, по существу:
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , amp;saddr , (socklen_t*)amp;saddr_size);
//fprintf(stderr,"%d",data_size);
if(data_size <0 )
{
fprintf(stderr,"Failed to get packetn");
printf("Recvfrom error , failed to get packetsn");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
и поэтому, чтобы остановить это, вы должны нажать CTRL-C.
Комментарии:
1. Это странно,
SSClient.exec_command
что он не блокируется. Что, если ты сделаешь что-нибудь подобноеsleep 60 amp;amp; ls
. Он также висит в течение 60 секунд?2. @MartinPrikryl Программа ждет 60 секунд, прежде чем продолжить.
3. «не прибегая к потоковой передаче», если вы хотите делать 2 вещи одновременно, вам нужна какая-то форма параллелизма. Ваш основной выбор-многопоточный или многопроцессный. Создание второго процесса, безусловно, можно рассматривать как «обращение к потоковой передаче», поэтому не совсем ясно, что вы хотите сделать. Вы можете либо запустить отдельный поток в том же процессе, либо создать новые потоки в новом процессе.
4.
if(data_size <0 )
: если read() или recv() возвращают -1, вы должны проверить errno. Это может быть EINTR/EAGAIN5. Какая система и оболочка у вас есть на сервере? В Ubuntu и bash я немедленно «заканчиваю» с
stdin, stdout, stderr = ssh.exec_command("sleep 60 amp;amp; ls"); print("Done");
Ответ №1:
Вам нужно отправить свой пароль в sudo
команду. Пожалуйста, включите tty
режим для выполнения вашей команды, передав get_pty = True
аргумент exec_command
вызову функции. А затем вам нужно передать свой пароль через ssh_stdin
файловый интерфейс.
def startPacketReceiver():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(RECV_IP_ADDRESS, username="pi", password="raspberry")
ssh.stdin, ssh_stdout, ssh_stderr = ssh.exec_command("gcc Code/test.c amp;amp; sudo ./a.out", get_pty=True)
print("raspberry", ssh_stdin) # Your password for sudo command
print("Done")
return ssh, ssh_stdin, ssh_stdout, ssh_stderr
А затем вы можете написать свой stopPacketReceiver
для отправки сигнала Ctrl-C.
def stopPacketReceiver(ssh, ssh_stdin, ssh_stdout, ssh_stderr):
print('x03', file=ssh_stdin) # Send Ctrl-C signal
print(ssh_stdout.read()) #print the stdout
print(ssh_stderr.read())
Ответ №2:
Я предлагаю взглянуть на демона(3)
Затем вы можете записывать СИГНАЛЫ или повторно открывать стандартный ввод. Зависит от того, что вы хотели бы сделать со своим скриптом python. (Если вы не хотите использовать какой-либо python, любую библиотеку python, кроме sys и os)
Редактировать:
Я почти уверен, что когда скрипт python завершит работу, ssh-соединение, очевидно, закроется, и поэтому любая программа, запущенная на этом tty пользователем, который инициировал соединение, будет прекращена. По этой причине ваша программа на языке си нуждается в демонизации, и, возможно, потребуется изменить ее uid и/или euid.
Несмотря на это, я попытался воспроизвести ваш код и столкнулся с аналогичной проблемой: скрипт python запускал команду, а затем печатал «Готово», но когда я попытался прочитать stdout, весь сценарий был приостановлен. Я думаю, что он ждал, когда скрипт вернет статус. Поэтому я внес следующие изменения:
try:
port = '22'
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('<host_name>', port=22, username='<username>',
password='<password>')
chan = client.get_transport().open_session()
chan.get_pty()
chan.exec_command("cd <script_directory>;
; gcc test.c; ./a.out")
while True:
print(chan.recv(1024))
finally:
client.close()
Цикл while здесь предназначен для получения выходных данных программы на языке си.
Но если вы закроете скрипт на python, за ним последует программа на языке си.
Я не слишком много копался в этой библиотеке.
ПРАВКА 2:
Посмотри наверх, нохуп
если вы не хотите использовать подход демона.