0

我在我的 RPi 上使用无线电发送器来控制家里的一些照明设备。我正在尝试实现时间控制,并且过去曾成功使用过“at”程序。

#!/usr/bin/python

import subprocess as sp
##### some code #####
sp.call(['at', varTime, '<<<', '\"sudo', './codesend', '111111\"'])

当我执行程序时,我收到

errmsg : 语法错误。最后看到的令牌:<

乱码时间

这个代码片段可以很好地处理每个命令本身(只要每个参数都来自字符串类型)。

必须以这种方式调用“at”:at 18:25 <<< "sudo ./codesend 111111"将命令保存在队列中(在“atq”中可见),因为sudo ./codesend 111111 | at 18:25只是直接执行命令并将执行记录在“/var/mail/ user ”中。

我的问题是,我怎样才能避免语法错误。 我在这个程序中使用了很多其他包,所以我必须继续使用 Python

我希望有人能解决这个问题,或者可以帮助找到我的错误。提前谢谢了

4

1 回答 1

2

前言:共享代码

将以下上下文视为此答案的两个分支的一部分。

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 中输入标准输入

<<<是外壳语法。它对 没有任何意义,如果作为字面参数给出at,它是完全正常的,并且预计会拒绝它。at

不过,您不需要调用 shell —— 您可以直接从本机 Python 执行相同的操作:

p = sp.Popen(['at', vartime], stdin=sp.PIPE)
p.communicate(cmd_str)

解决方案 B:显式调用 Shell

此外,<<<不是/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()或(根据我们的 Python 版本);pipes.quote()这对于避免在我们的软件中创建 shell 注入漏洞至关重要。

于 2018-07-08T18:37:26.580 回答