我在RPi上使用无线电发射器来控制家里的一些照明设备。我正在尝试实现时间控制,并且过去曾成功使用"at"程序。
#!/usr/bin/python
import subprocess as sp
##### some code #####
sp.call(['at', varTime, '<<<', '"sudo', './codesend', '111111"'])
当我执行程序时,我收到
错误:语法错误。最后看到的令牌:<</em>
乱码时间
这个代码片段本身可以很好地处理每个命令(只要每个参数都来自字符串类型(。
有必要以这种方式调用"at":at 18:25 <<< "sudo ./codesend 111111"
将命令保存在队列中(可在"atq"中查看(, 因为sudo ./codesend 111111 | at 18:25
只是直接执行命令并在"/var/mail/user"中写下执行。
我的问题是,我怎样才能避免语法错误。我在这个程序中使用了很多其他包,所以我必须继续使用 Python
我希望有人能解决这个问题,或者可以帮助找到我的错误。 提前非常感谢
前言:共享代码
请考虑以下上下文作为此答案的两个分支的一部分。
import subprocess as sp
try:
from shlex import quote # Python 3
except ImportError:
from pipes import quote # Python 2
# given the command you want to schedule, as an array...
cmd = ['sudo', './codesend', '111111']
# ...generate a safely shell-escaped string.
cmd_str = ' '.join(quote(x) for x in cmd))
解决方案 A:Python 中的 Feed Stdin
<<<
是外壳语法。它对at
没有任何意义,如果作为字面上的论证给出,at
拒绝它是完全正常的,也是意料之中的。
不过,你不需要调用 shell——你可以直接从原生 Python 做同样的事情:
p = sp.Popen(['at', vartime], stdin=sp.PIPE)
p.communicate(cmd_str)
解决方案 B:显式调用外壳
此外,<<<
不是/bin/sh
语法 - 它是bash,ksh和其他扩展;因此你不能仅仅通过添加shell=True
标志(它使用/bin/sh
,因此只保证POSIX基线功能(可靠地获取它。如果需要,则需要显式调用具有该功能的 shell,如下所示:
bash_script = '''
at "$1" <<<"$2"
'''
sp.call(['bash', '-c', bash_script,
'_', # this is $0 for that script
vartime, # this is its $1
cmd_str, # this is its $2
])
无论哪种情况,请注意,在从参数列表中生成 shell 命令时,我们使用shlex.quote()
或pipes.quote()
(适用于我们的 Python 版本(;这对于避免在我们的软件中创建 shell 注入漏洞至关重要。