1

Context:

I have been tasked with researching how to execute linux commands using python. Since I am on windows, I have to execute 'wsl' first to swtich to the ubuntu distro I downloaded from microsoft store. Note that I am not a python programmer but currently working as a java intern. Although the python project/script will be deployed on a linux machine right now this is the only way for me to test the program.

Problem:

The problem I am getting is that if I have an list of commands and I am trying to execute them one by one, for some reason at the end of every command a return carriage is being found because apparently in windows DOS uses carriage return and line feed ("\r\n") as a line ending whereas in linux uses just line feed ("\n").

This is the python script

import subprocess


   
commands=["ls -al ~","pwd"]

# Initialize the WSL process
process = subprocess.Popen("wsl", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
# Execute each command in WSL
for command in commands:
    process.stdin.write((command)+"\n")
    
# Close the stdin and wait for the process to complete
process.stdin.close()
process.wait()
# Read and print the response from WSL
output = process.stdout.read()
print("WSL:", output)



I tried stripping '\r' but it makes absolutely zero difference as if it doesn't understand what '\r' is. Here is the output:

WSL: ls: cannot access '~'$'\r': No such file or directory
-bash: line 2: $'pwd\r': command not found

Solution 1 write converted \n to \r\n, try this :

import subprocess

commands=["ls -al ~","pwd"]

# Initialize the WSL process
process = subprocess.Popen("wsl", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
# Execute each command in WSL
with open(process.stdin.fileno(), mode='w', newline='') as f:
    for command in commands:
        f.write((command)+'\n')

# Close the stdin and wait for the process to complete
# process.stdin.close()
# process.wait()
# Read and print the response from WSL
output = process.stdout.read()
print("WSL:", output)

Update: Thanks for the solution but and I also figured out a solution myself. It works like a charm. Solution 2 by questioner

import subprocess
import shlex

# Define a list of commands
commands = ["ls -al ~", "pwd", "pwd"]

# Initialize the WSL process and execute each command
for command in commands:
    command_list = shlex.split(command)
    #Remove the ['wsl'] if this script is ran in linux environment
    #Also I am assuming that the default shell is bash
    #If it's not then enter into bash mode(or anyother) by replacing 'wsl' with 'bash'

    result = subprocess.run(['wsl'] + command_list, stdout=subprocess.PIPE, text=True)
    print("WSL:", result.stdout)

8
  • 2
    Why are you passing text=True to popen? Looks like that's the source of the extra CRs. Commented Jan 22, 2024 at 11:30
  • 1
    If you have WSL Ubuntu running, why not do everything under WSL? Then there's no need to open "wsl" separately. Commented Jan 22, 2024 at 11:33
  • 1
    Note that lots of Linux commands have near-enough equivalents in Python; you may have to do some extra steps to get similar output (but perhaps you don't even want that), like sorting or providing more details as in ls -l. It is a fairly odd thing to execute Linux commands through Python. my advice: for a simple set of commands, use a bash script; for a complicated set of commands, write a proper (Python) program Commented Jan 22, 2024 at 11:35
  • A much simpler solution is for command in commands: print(subprocess.run(['wsl'] + shlex.split(command), text=True).stdout) and get rid of the whole attempt to use Popen Commented Jan 22, 2024 at 11:35
  • 1
    Does this answer your question? Run linux commands from windows in python script Commented Jan 22, 2024 at 11:37

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.