提问人:Durable Metal 提问时间:7/21/2022 更新时间:7/21/2022 访问量:103
如何在 Python3 代码中实现 bash oneliner?
How to implement bash oneliner into Python3 code?
问:
我有 bash oneliner,但我不能使用它实现到 python3 中并在 Rhel 服务器上运行它。
for i in {5000..10000}; do if grep "no such user" <(id $i 2>&1 ) > /dev/null; then echo $i ; break ; fi; done
我已经试过了
print(subprocess.check_output('bash -c "for i in {5000..10000}; do if grep "no such user" <(id $i 2>&1 ) > /dev/null; then echo $i ; break ; fi ; done" ', shell=True).decode())
和这个
p1 = Popen(["for i in {5000..10000}; do if grep "no such user" <(id $i 2>&1 ) > /dev/null; then echo $i ; break ; fi; done"], stdout=PIPE)
print p1.communicate()
也试过这个
command = '''
for i in {5000..10000}
do
if grep "no such user" <(id $i 2>&1 ) > /dev/null
then echo $i
break
fi
done
'''
uid = subprocess.run(command, capture_output=True, shell=True)
我总是得到 SyntaxError:语法无效 或
CompletedProcess(args='\n for i in {5000..10000}\ndo\n if grep "no such user" <(id $i 2>&1 ) > /dev/null\n then echo $i\n break\n fi\ndone\n', returncode=1, stdout=b'', stderr=b'/bin/sh: -c: line 3: syntax error near unexpected token `(\'\n/bin/sh: -c: line 3: ` if grep "no such user" <(id $i 2>&1 ) > /dev/null\'\n')
你能帮帮我,说说我做错了什么吗?我已经失去了无数小时的调试时间,并希望得到您的帮助。
答:
2赞
Barmar
7/21/2022
#1
在 Python 中执行循环和输出检查。
for i in range(5000, 10001):
output = subprocess.check_output(['id', str(i)], stderr=subprocess.DEVNULL, encoding='utf-8')
if 'no such user' in output:
print(i)
break
Python 还有一个用于搜索用户数据库的 pwd
模块。
from pwd import getpwuid
for i in range(5000, 10001):
try:
getpwuid(i)
except KeyError:
print(i)
break
评论
1赞
Charles Duffy
7/21/2022
Re:执行该操作的库函数 -- pypi.org/project/getent;也可以使用 FFI 直接调用 libc 函数,而无需做太多工作。同样相关的是用于列出用户和组的 python 脚本id $i
2赞
Barmar
7/21/2022
@CharlesDuffy 这些看起来不太容易使用(文档非常备用,我不知道它是否需要 uid 参数),但我找到了内置模块。getent
pwd
1赞
Charles Duffy
7/24/2022
是的,FWIW 可以用 uid 代替名称; 正确返回 的条目,并且(在我有条目的 Linux 盒子上)首先返回 root 的条目,然后返回 dbus 用户的条目,这是我的发行版分配给 UID 4 的帐户,同时忽略那些没有分配帐户的 UID——因此可以在每个命令行上传递多个 UID,而不是对每个 UID 进行单独的调用, 允许 xargs 类型折叠。getent
getent passwd 0
root
getent passswd 0 1 2 3 4
2赞
Charles Duffy
7/21/2022
#2
虽然更好的答案是在 Python 中完成这一切(这将大大提高效率),但你没有理由不能用子进程来做到这一点。
使用三引号的原始字符串,以便您的 bash 代码存储在 Python 字符串中,而无需对其进行任何修改:
#!/usr/bin/env python
import subprocess
bash_code=r'''
for i in {5000..10000}; do if grep "no such user" <(id "$i" 2>&1 ) > /dev/null; then echo "$i" ; break ; fi; done
'''
p = subprocess.run(['bash', '-c', bash_code], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f"stdout is: {f.stdout}")
评论
id
grep
passwd
shell=True
/bin/sh
bash
sh
bash
bash
{1..2}
printf '%s\n' {50000..10000} | xargs -d $'\n' getent passwd | cut -d: -f3