(For more resources related to this topic, see here.)
Executing a remote shell command using telnet
If you need to connect an old network switch or router via telnet, you can do so from a Python script instead of using a bash script or an interactive shell. This recipe will create a simple telnet session. It will show you how to execute shell commands to the remote host.
You need to install the telnet server on your machine and ensure that it’s up and running. You can use a package manager that is specific to your operating system to install the telnet server package. For example, on Debian/Ubuntu, you can use apt-get or aptitude to install the telnetd package, as shown in the following command:
$ sudo apt-get install telnetd $ telnet localhost
How to do it…
Let us define a function that will take a user’s login credentials from the command prompt and connect to a telnet server.
Upon successful connection, it will send the Unix ‘ls’ command. Then, it will display the output of the command, for example, listing the contents of a directory.
Listing 7.1 shows the code for a telnet session that executes a Unix command remotely as follows:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter - 7 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import getpass import sys import telnetlib def run_telnet_session(): host = raw_input("Enter remote hostname e.g. localhost:") user = raw_input("Enter your remote account: ") password = getpass.getpass() session = telnetlib.Telnet(host) session.read_until("login: ") session.write(user + "n") if password: session.read_until("Password: ") session.write(password + "n") session.write("lsn") session.write("exitn") print session.read_all() if __name__ == '__main__': run_telnet_session()
If you run a telnet server on your local machine and run this code, it will ask you for your remote user account and password. The following output shows a telnet session executed on a Debian machine:
$ python 7_1_execute_remote_telnet_cmd.py Enter remote hostname e.g. localhost: localhost Enter your remote account: faruq Password: ls exit Last login: Mon Aug 12 10:37:10 BST 2013 from localhost on pts/9 Linux debian6 2.6.32-5-686 #1 SMP Mon Feb 25 01:04:36 UTC 2013 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. You have new mail. faruq@debian6:~$ ls down Pictures Videos Downloads projects yEd Dropbox Public env readme.txt faruq@debian6:~$ exit logout
How it works…
This recipe relies on Python’s built-in telnetlib networking library to create a telnet session. The run_telnet_session() function takes the username and password from the command prompt. The getpass module’s getpass() function is used to get the password as this function won’t let you see what is typed on the screen.
In order to create a telnet session, you need to instantiate a Telnet() class, which takes a hostname parameter to initialize. In this case, localhost is used as the hostname. You can use the argparse module to pass a hostname to this script.
The telnet session’s remote output can be captured with the read_until() method. In the first case, the login prompt is detected using this method. Then, the username with a new line feed is sent to the remote machine by the write() method (in this case, the same machine accessed as if it’s remote). Similarly, the password was supplied to the remote host.
Then, the ls command is sent to be executed. Finally, to disconnect from the remote host, the exit command is sent, and all session data received from the remote host is printed on screen using the read_all() method.
Copying a file to a remote machine by SFTP
If you want to upload or copy a file from your local machine to a remote machine securely, you can do so via Secure File Transfer Protocol (SFTP).
This recipe uses a powerful third-party networking library, Paramiko, to show you an example of file copying by SFTP, as shown in the following command. You can grab the latest code of Paramiko from GitHub (https://github.com/paramiko/paramiko) or PyPI:
$ pip install paramiko
How to do it…
This recipe takes a few command-line inputs: the remote hostname, server port, source filename, and destination filename. For the sake of simplicity, we can use default or hard-coded values for these input parameters.
In order to connect to the remote host, we need the username and password, which can be obtained from the user from the command line.
Listing 7.2 explains how to copy a file remotely by SFTP, as shown in the following code:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter - 7 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import argparse import paramiko import getpass SOURCE = '7_2_copy_remote_file_over_sftp.py' DESTINATION ='/tmp/7_2_copy_remote_file_over_sftp.py ' def copy_file(hostname, port, username, password, src, dst): client = paramiko.SSHClient() client.load_system_host_keys() print " Connecting to %s n with username=%s... n" %(hostname,username) t = paramiko.Transport((hostname, port)) t.connect(username=username,password=password) sftp = paramiko.SFTPClient.from_transport(t) print "Copying file: %s to path: %s" %(SOURCE, DESTINATION) sftp.put(src, dst) sftp.close() t.close() if __name__ == '__main__': parser = argparse.ArgumentParser(description='Remote file copy') parser.add_argument('--host', action="store", dest="host", default='localhost') parser.add_argument('--port', action="store", dest="port", default=22, type=int) parser.add_argument('--src', action="store", dest="src", default=SOURCE) parser.add_argument('--dst', action="store", dest="dst", default=DESTINATION) given_args = parser.parse_args() hostname, port = given_args.host, given_args.port src, dst = given_args.src, given_args.dst username = raw_input("Enter the username:") password = getpass.getpass("Enter password for %s: " %username) copy_file(hostname, port, username, password, src, dst)
If you run this script, you will see an output similar to the following:
$ python 7_2_copy_remote_file_over_sftp.py Enter the username:faruq Enter password for faruq: Connecting to localhost with username=faruq... Copying file: 7_2_copy_remote_file_over_sftp.py to path: /tmp/7_2_copy_remote_file_over_sftp.py
How it works…
This recipe can take the various inputs for connecting to a remote machine and copying a file over SFTP.
This recipe passes the command-line input to the copy_file() function. It then creates a SSH client calling the SSHClient class of paramiko. The client needs to load the system host keys. It then connects to the remote system, thus creating an instance of the transport class. The actual SFTP connection object, sftp, is created by calling the SFTPClient.from_transport() function of paramiko. This takes the transport instance as an input.
After the SFTP connection is ready, the local file is copied over this connection to the remote host using the put() method.
Finally, it’s a good idea to clean up the SFTP connection and underlying objects by calling the close() method separately on each object.