简体   繁体   中英

Python subprocess is not working as expected for find command

I am trying to find out orphan files on the node in python. Below is the code snippet

#!/usr/bin/python
import subprocess
try:
        s = subprocess.check_output(["find", "/", "-fstype", "proc", "-prune", "-o", "\( -nouser -o -nogroup \)", "-print"])
except subprocess.CalledProcessError as e:
    print e.output
else:
    if len(s) > 0:
        print ("List of Orphan Files are \n%s\n" % s)
    else:
        print ("Orphan Files does not Exists on the NE")

When I try to run this python code

> python test.py 
find: paths must precede expression: \( -nouser -o -nogroup \)
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

When I run the same command on CLI it is working fine.

> find / -fstype proc -prune -o \( -nouser -o -nogroup \) -print
/root/a

Few of you suggested to use shell=true, as per the python doc for subprocess it is security hazard. Warning Using shell=True can be a security hazard.

只需将shell = True添加到您的check_output

s = subprocess.check_output(["find", "/", "-fstype", "proc", "-prune", "-o", "\( -nouser -o -nogroup \)", "-print"], shell=True)

You should split the command on every whitespace. The easiest way to do this is with shlex.split :

import shlex
import subprocess

cmd = shlex.split('find / -fstype proc -prune -o \( -nouser -o -nogroup \) -print')
subprocess.check_output(cmd)

You can set the shell=True option and then just pass the entire shell command. I think the whitespace is causing the issue.

s = subprocess.check_output("find / -fstype proc -prune -o \( -nouser -o -nogroup \) -print", shell=True)

Note this warning relating to setting shell=True . Basically don't do it if the input comes from an external source (like user input). In this case it should therefore be fine.

I tried your script and got the same error as you did. I was trying different things and found something that worked for me. I changed

-print

to

-exec

and it worked. But I am not sure why this was the behavior.

Each command line parameter must be passed as a separate list item, including the parentheses and their contents:

s = subprocess.check_output(["find", "/", "-fstype", "proc", "-prune", "-o",
                            "(", "-nouser", "-o", "-nogroup", ")", 
                            "-print"])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM