OSError: [Errno 13] Permission denied: '/dev/ttyACM0' - using pyserial from Python to Arduino
OSError: [Errno 13] Permission denied: '/dev/ttyACM0' - using pyserial from Python to Arduino
环境
- Linux 薄荷 17.1
- Python 2.7
- pyserial 2.7
- Arduino UNO rv3
期望的行为
我正在尝试将三个值从 Python 应用程序发送到 Arduino。
从终端执行以下操作时有效:
$ python
$ import serial
$ import struct
$ ser = serial.Serial('/dev/ttyACM0', 9600)
$ ser.write(struct.pack('>3B', 255, 0, 0))
当前行为
在 Python 文件中使用相同代码时不起作用,即:
import serial
import struct
ser = serial.Serial('/dev/ttyACM0', 9600)
ser.write(struct.pack('>3B', red_value, green_value, blue_value))
错误信息
$ sudo tail -100 /var/log/apache2/error.log
OSError: [Errno 13] Permission denied: '/dev/ttyACM0'
疑难解答
权限
申请文件:
$ ls -l
-rwxr-xr-x 1 myname mygroupname 114146 Jan 9 19:16 my_application.py
ttyACM0:
ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Jan 9 20:12 /dev/ttyACM0
群组
所有者所属的群组:
$ groups
mygroupname adm dialout cdrom sudo dip plugdev lpadmin sambashare
由于互联网上的各种建议,我还通过系统设置 > 用户和组将所有者添加到 tty
组。这没有效果。
可用串口
$ dmesg | grep tty
[ 0.000000] console [tty0] enabled
[ 3390.614686] cdc_acm 3-2:1.0: ttyACM0: USB ACM device
更新
我可以强制它在以下条件下工作:
01. 世界权限必须设置为 rw
即:
sudo chmod 666 /dev/ttyACM0
02. Arduino IDE 串行监视器需要打开。
然而,这些条件是不可持续的,因为:
- 每次连接 USB 时都会重置权限。
- Arduino IDE 串行监视器不需要打开。
文件的权限对程序运行的用户没有影响
当您以交互方式登录时,您有权使用 /dev/ttyACM0
当你的脚本是 运行(大概是 apache 用户)时它没有权限
您需要更改 /dev/ttyACM0
的权限
请参阅此处的第二个答案How can I programmatically set permissions on my char device,了解更改 udev 权限以使文件具有正确权限的示例
下面对第一个答案的一些想法进行充实(我试图将此内容添加到那个答案中并接受,但编辑被拒绝)。我不是该领域的专家,因此请仅使用此信息来支持您自己的研究。
您可以执行以下操作之一:
01. 更改 /dev/ttyACM0
的权限,使世界拥有 read
和 write
特权(您可能不想做的事情) - 尽管您可能会发现每次插入设备时它们都会重置,例如:
sudo chmod 666 /dev/ttyACM0
02. 在 /etc/udev/rules.d
中创建一个规则来设置设备的权限(需要重新启动):
# navigate to rules.d directory
cd /etc/udev/rules.d
#create a new rule file
sudo touch my-newrule.rules
# open the file
sudo vim my-newrule.rules
# add the following
KERNEL=="ttyACM0", MODE="0666"
这还将世界权限设置为 read
和 write
,您可能不想这样做。
有关此方法的详细信息,请参阅以下答案:
https://unix.stackexchange.com/a/48596/92486
03. 第三个选项,这是我实现的选项,将 Apache 用户添加到 dialout
组,这样如果脚本正在 运行,然后它就可以访问设备了。
a) 找到 Apache 配置文件的位置,然后在该文件中搜索 User
设置:
# open file in editor
sudo vim /etc/apache2/apache2.conf
# search for User setting
/User
您可能会发现类似这样的内容:
# These need to be set in /etc/apache2/envvars
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}
b) 退出 vim 并在 /etc/apache2/envvars
中搜索 APACHE_RUN_USER
(如果上述情况适用):
# open file in editor
sudo vim /etc/apache2/envvars
# search for APACHE_RUN_USER
/APACHE_RUN_USER
您可能会发现类似以下内容:
export APACHE_RUN_USER=www-data
c) 将用户 www-data
添加到 dialout
组:
sudo usermod -a -G dialout www-data
d) 重启。
由于 Apache 用户已添加到 dialout
组,脚本现在应该能够访问设备。
进一步阅读
如何找到 Apache 配置文件的位置:
根据接受的答案,我可以将以下内容添加到我的 setup.sh
脚本中
printf "KERNEL==\"ttyACM0\", MODE=\"0666\"" | sudo tee /etc/udev/rules.d/si-ct.rules
环境
- Linux 薄荷 17.1
- Python 2.7
- pyserial 2.7
- Arduino UNO rv3
期望的行为
我正在尝试将三个值从 Python 应用程序发送到 Arduino。
从终端执行以下操作时有效:
$ python
$ import serial
$ import struct
$ ser = serial.Serial('/dev/ttyACM0', 9600)
$ ser.write(struct.pack('>3B', 255, 0, 0))
当前行为
在 Python 文件中使用相同代码时不起作用,即:
import serial
import struct
ser = serial.Serial('/dev/ttyACM0', 9600)
ser.write(struct.pack('>3B', red_value, green_value, blue_value))
错误信息
$ sudo tail -100 /var/log/apache2/error.log
OSError: [Errno 13] Permission denied: '/dev/ttyACM0'
疑难解答
权限
申请文件:
$ ls -l
-rwxr-xr-x 1 myname mygroupname 114146 Jan 9 19:16 my_application.py
ttyACM0:
ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Jan 9 20:12 /dev/ttyACM0
群组
所有者所属的群组:
$ groups
mygroupname adm dialout cdrom sudo dip plugdev lpadmin sambashare
由于互联网上的各种建议,我还通过系统设置 > 用户和组将所有者添加到 tty
组。这没有效果。
可用串口
$ dmesg | grep tty
[ 0.000000] console [tty0] enabled
[ 3390.614686] cdc_acm 3-2:1.0: ttyACM0: USB ACM device
更新
我可以强制它在以下条件下工作:
01. 世界权限必须设置为 rw
即:
sudo chmod 666 /dev/ttyACM0
02. Arduino IDE 串行监视器需要打开。
然而,这些条件是不可持续的,因为:
- 每次连接 USB 时都会重置权限。
- Arduino IDE 串行监视器不需要打开。
文件的权限对程序运行的用户没有影响
当您以交互方式登录时,您有权使用 /dev/ttyACM0
当你的脚本是 运行(大概是 apache 用户)时它没有权限
您需要更改 /dev/ttyACM0
的权限请参阅此处的第二个答案How can I programmatically set permissions on my char device,了解更改 udev 权限以使文件具有正确权限的示例
下面对第一个答案的一些想法进行充实(我试图将此内容添加到那个答案中并接受,但编辑被拒绝)。我不是该领域的专家,因此请仅使用此信息来支持您自己的研究。
您可以执行以下操作之一:
01. 更改 /dev/ttyACM0
的权限,使世界拥有 read
和 write
特权(您可能不想做的事情) - 尽管您可能会发现每次插入设备时它们都会重置,例如:
sudo chmod 666 /dev/ttyACM0
02. 在 /etc/udev/rules.d
中创建一个规则来设置设备的权限(需要重新启动):
# navigate to rules.d directory
cd /etc/udev/rules.d
#create a new rule file
sudo touch my-newrule.rules
# open the file
sudo vim my-newrule.rules
# add the following
KERNEL=="ttyACM0", MODE="0666"
这还将世界权限设置为 read
和 write
,您可能不想这样做。
有关此方法的详细信息,请参阅以下答案:
https://unix.stackexchange.com/a/48596/92486
03. 第三个选项,这是我实现的选项,将 Apache 用户添加到 dialout
组,这样如果脚本正在 运行,然后它就可以访问设备了。
a) 找到 Apache 配置文件的位置,然后在该文件中搜索 User
设置:
# open file in editor
sudo vim /etc/apache2/apache2.conf
# search for User setting
/User
您可能会发现类似这样的内容:
# These need to be set in /etc/apache2/envvars
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}
b) 退出 vim 并在 /etc/apache2/envvars
中搜索 APACHE_RUN_USER
(如果上述情况适用):
# open file in editor
sudo vim /etc/apache2/envvars
# search for APACHE_RUN_USER
/APACHE_RUN_USER
您可能会发现类似以下内容:
export APACHE_RUN_USER=www-data
c) 将用户 www-data
添加到 dialout
组:
sudo usermod -a -G dialout www-data
d) 重启。
由于 Apache 用户已添加到 dialout
组,脚本现在应该能够访问设备。
进一步阅读
如何找到 Apache 配置文件的位置:
根据接受的答案,我可以将以下内容添加到我的 setup.sh
脚本中
printf "KERNEL==\"ttyACM0\", MODE=\"0666\"" | sudo tee /etc/udev/rules.d/si-ct.rules