我正在尝试使用bluepy扫描BLE设备。我的 scan.py 代码是-
from bluepy.btle import Scanner, DefaultDelegate
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev:
print "Discovered device", dev.addr
elif isNewData:
print "Received new data from", dev.addr
# prepare scanner
scanner = Scanner().withDelegate(ScanDelegate())
# scan for 5 seconds
devices = scanner.scan(5.0)
for dev in devices:
print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
for (adtype, desc, value) in dev.getScanData():
print " %s = %s" % (desc, value)
根据文档(最后提到为注释)-
(1) LE scanning must be run as root
这意味着我们需要使用 sudo
运行脚本。我以-
sudo python scan.py
基本上 bluepy-helper 需要 sudo
进行扫描。必须设置 blupe-helper 的功能才能在没有 sudo
的情况下运行代码。根据{{3}},我做到了-
sudo setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python2.7/site-packages/bluepy/bluepy-helper
现在从终端上运行扫描代码时,不会像-
那样使用sudo
python scan.py
最后,我制作了一个Dockerfile-
FROM arm32v7/python:2.7.15-jessie
WORKDIR /usr/app/gfi_ble
COPY . /usr/app/gfi_ble
RUN chmod 755 ./setcap_for_bluepy_helper.sh
RUN pip install -r requirements.txt
CMD ["./setcap_for_bluepy_helper.sh", "--", "python", "src/scan.py"]
setcap_for_bluepy_helper.sh 的内容为-
#!/bin/bash
cmd="$@"
>&2 setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python2.7/site-packages/bluepy/bluepy-helper
exec $cmd
图像创建成功,但是当我运行容器时,出现类似-的错误
Creating con_gfi_ble ... done
Attaching to con_gfi_ble
con_gfi_ble | 2019-01-12 23:06:24+0000 [-] Unhandled Error
con_gfi_ble | Traceback (most recent call last):
con_gfi_ble | File "/usr/app/gfi_ble/src/scan.py", line 17, in new_devices
con_gfi_ble | devices = scanner.scan(5.0)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 852, in scan
con_gfi_ble | self.start(passive=passive)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 789, in start
con_gfi_ble | self._startHelper(iface=self.iface)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 284, in _startHelper
con_gfi_ble | preexec_fn = preexec_function)
con_gfi_ble | File "/usr/local/lib/python2.7/subprocess.py", line 394, in __init__
con_gfi_ble | errread, errwrite)
con_gfi_ble | File "/usr/local/lib/python2.7/subprocess.py", line 1047, in _execute_child
con_gfi_ble | raise child_exception
con_gfi_ble | exceptions.OSError: [Errno 1] Operation not permitted
con_gfi_ble |
问题: 异常是什么?OSError:[Errno 1]不允许操作?
当我从Terminal运行它时,我的代码很好。容器怎么了?任何想法!
答案 0 :(得分:2)
Docker容器运行时功能降低。这样可以通过运行不带名称空间的内核命令并访问容器外部主机的某些部分(例如原始网络接口或物理设备)来防止容器内部的根逃脱容器。如果需要,您需要在外部向容器添加功能,但是要理解,这会降低docker默认设置所提供的安全性。
在docker run
中,它看起来像:
docker run --cap-add=NET_ADMIN --cap-add=NET_RAW ...
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
在撰写文件中,它看起来像:
version: '2'
services:
app:
image: your_image
cap_add:
- NET_ADMIN
- NET_RAW
参考:https://docs.docker.com/compose/compose-file/
这不适用于群体模式。在群体模式下,添加功能来运行命令的工作正在进行中。如果需要,可以使用一些丑陋的解决方法。
请注意,您不应在容器内运行sudo
。这样做意味着一切都可以提升自己的生根,并破坏了以用户身份运行任何东西的目的。相反,您应该以root用户身份启动容器,并尽快移交给普通用户,这是一种单向操作。