Lyra Orwell
Lyra Orwell

Reputation: 1258

Is there a method of executing a command then continue the program without command termination

Hi I am trying to create a function which remotely executes my packet sniffing script on my raspberry pi using paramiko and 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 && sudo ./a.out")
    print("Done")

The test.c file is the packet sniffing script. It will only terminate with a CTRL-C (or equivalent method). It does not terminate naturally/eventually.

I want to be able to start the receiver and then quit the receiver e.g:

startPacketReceiver()
...
stopPacketReceiver()

Currently when I run the python script I never get the "Done" print message, meaning that the program is hung on the exec_command and will not continue until it is terminated.

Additional Info

The test.c file loops infinitely, essentially:

while(1)
{
    saddr_size = sizeof saddr;
    //Receive a packet
    data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
    //fprintf(stderr,"%d",data_size);
    if(data_size <0 )
    {
        fprintf(stderr,"Failed to get packet\n");
        printf("Recvfrom error , failed to get packets\n");
        return 1;
    }
    //Now process the packet
    ProcessPacket(buffer , data_size);
}

and so to stop it you must CTRL-C it.

Upvotes: 0

Views: 523

Answers (2)

Fedgyma
Fedgyma

Reputation: 46

I suggest taking a look at daemon(3)

Then you can capture SIGNALS or reopen standard input. Depends on what you would like to do with your python script. (If you don't want to use any python any python library other than sys and os)

EDIT:

I am pretty sure when the python script will terminate the ssh connection will obviously close and so any program running on that tty by the user who initiated the connection will be terminated. For that reason your c program needs to be daemonized and may need to have its uid and/or euid changed.

Despite that i tried to reproduce your code and I ran into a similar problem: the python script was running the command then print "Done" but as I tried to read stdout, the entire script was pause. I think it was waiting for the script return status. So i did the following changes:

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()

The while loop here is to get output of the c program. But if you close the python script the c program will follow. I did not dug to much into this library.

EDIT 2:

Look up nohup

if you don't want to use de daemon approach.

Upvotes: 1

Fractal
Fractal

Reputation: 814

You need to send your password to the sudo command. Please enable tty mode for executing your command by passing get_pty = True argument to exec_command function call. And then you need to pass your password through ssh_stdin file interface.

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 && 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

And then you can write your stopPacketReceiver to send Ctrl-C signal.

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())

Upvotes: 1

Related Questions