Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: April 20, 2025
Secure Shell (SSH) and Secure Copy Protocol (SCP) are commonly used tools for secure remote access and file transfer in Linux environments. Automating these tasks using Python’s subprocess.Popen can be helpful in scenarios where password authentication is required.
In this tutorial, we’ll learn how to securely send a password using subprocess.Popen while avoiding common security pitfalls.
The subprocess module in Python enables us to spawn new processes, connect to their input, output, and error pipes, and obtain their return codes. The Popen class is particularly useful for interacting with processes programmatically.
Here’s a basic example to run an SSH command using subprocess.Popen:
import subprocess
process = subprocess.Popen([
'ssh', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
This approach works well when using SSH keys for authentication. If password authentication is needed, subprocess.Popen doesn’t support sending it securely by default.
Passing passwords via standard input or command-line arguments introduces several risks:
Tools such as sshpass or pexpect help reduce these risks effectively.
sshpass is a utility that allows non-interactive SSH authentication by passing a password via a command-line argument or standard input.
Let’s install sshpass using the system’s package manager:
$ sudo apt install sshpass # Debian-based systems
$ sudo yum install sshpass # RHEL-based systems
Once installed, we can use it to invoke SSH commands.
Let’s use sshpass to run an SSH command from Python:
import subprocess
password = "your_password"
command = [
'sshpass', '-p', password, 'ssh', 'user@remote_host', 'ls'
]
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
Although the code works, there are security concerns to be aware of.
While sshpass helps with automation, there are notable concerns:
These concerns make sshpass less ideal for secure environments. Let’s look at a more secure alternative.
pexpect simulates user interaction, allowing secure password entry and improved automation handling.
Let’s install pexpect using pip:
$ pip install pexpect
With pexpect ready, let’s automate SSH connections more securely.
The following example demonstrates how to automate SSH login using pexpect:
import pexpect
user = "user"
host = "remote_host"
password = "your_password"
command = "ls"
ssh_command = f"ssh {user}@{host} {command}"
child = pexpect.spawn(ssh_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())
Let’s extend the same approach to handle file transfers.
We can automate SCP transfers securely using pexpect:
import pexpect
user = "user"
host = "remote_host"
password = "your_password"
local_file = "file.txt"
remote_path = "/home/user/file.txt"
scp_command = f"scp {local_file} {user}@{host}:{remote_path}"
child = pexpect.spawn(scp_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())
Aside from convenience, pexpect improves the overall security posture.
Using pexpect offers several security benefits:
These advantages make pexpect a preferable option for password-based automation.
Although password authentication can be automated, it’s usually better to use SSH keys for stronger security. Let’s walk through setting up SSH key authentication.
To create a new key pair, let’s use the ssh-keygen command:
$ ssh-keygen -t rsa -b 4096
Once the keys are generated, we place the public key on the remote system.
Let’s copy the public key to the remote host:
$ ssh-copy-id user@remote_host
Now, we can use key-based authentication in our Python script.
Once the SSH key is in place, let’s use it in Python:
import subprocess
process = subprocess.Popen([
'ssh', '-i', '/path/to/private_key', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())
SSH keys provide a more secure and efficient way to automate authentication in Python.
In this article, we saw how automating SSH and SCP operations using subprocess.Popen is possible but involves security challenges when passwords are required. Tools like pexpect offer a safer alternative to sshpass. However, using SSH keys remains the most secure and efficient method. By following these best practices, we can build robust and secure automation workflows.