我有一个可以在 Windows 上运行的 python 脚本,但在 Ubuntu 上运行它却很困难。
测试.py
#!/usr/bin/env python3
"""
https://pymodbustcp.readthedocs.io/en/latest/examples/server_allow.html
An example of Modbus/TCP server which allow modbus read and/or write only from
specific IPs.
Run this as root to listen on TCP privileged ports (<= 1024).
"""
import argparse
from pyModbusTCP.server import ModbusServer, DataHandler
from pyModbusTCP.constants import EXP_ILLEGAL_FUNCTION
# some const
ALLOW_R_L = ['127.0.0.1', '192.168.0.104']
ALLOW_W_L = ['127.0.0.1']
# a custom data handler with IPs filter
class MyDataHandler(DataHandler):
def read_coils(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
return super().read_coils(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_d_inputs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
return super().read_d_inputs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_h_regs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
return super().read_h_regs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def read_i_regs(self, address, count, srv_info):
if srv_info.client.address in ALLOW_R_L:
return super().read_i_regs(address, count, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def write_coils(self, address, bits_l, srv_info):
if srv_info.client.address in ALLOW_W_L:
return super().write_coils(address, bits_l, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
def write_h_regs(self, address, words_l, srv_info):
if srv_info.client.address in ALLOW_W_L:
return super().write_h_regs(address, words_l, srv_info)
else:
return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)
if __name__ == '__main__':
# parse args
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', type=str, default='localhost', help='Host (default: localhost)')
parser.add_argument('-p', '--port', type=int, default=502, help='TCP port (default: 502)')
args = parser.parse_args()
# init modbus server and start it
server = ModbusServer(host=args.host, port=args.port, data_hdl=MyDataHandler())
server.start()
当我从 SSH 运行此程序时,我得到:
Traceback (most recent call last):
File "/home/ben/anaconda3/lib/python3.7/site-packages/pyModbusTCP/server.py", line 989, in start
self._service.server_bind()
File "/home/ben/anaconda3/lib/python3.7/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
PermissionError: [Errno 13] Permission denied
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 69, in <module>
server.start()
File "/home/ben/anaconda3/lib/python3.7/site-packages/pyModbusTCP/server.py", line 992, in start
raise ModbusServer.NetworkError(e)
pyModbusTCP.server.NetworkError: [Errno 13] Permission denied
ls -la
如果我在目录中执行:
total 12
drwxrwxr-x 2 ben ben 4096 Aug 7 10:57 .
drwxr-xr-x 5 ben ben 4096 Aug 7 10:50 ..
-rw-rw-r-- 1 ben ben 2522 Aug 7 10:54 test.py
这是权限问题吗?
答案1
您的脚本已经回答了这个问题:
Run this as root to listen on TCP privileged ports (<= 1024).
在大多数类 Unix 系统上,接收端口 1-1024 上的连接需要权限 - 通常是 root(UID 0),或者具有权限cap_net_bind_service
(Linux 特定),等等。
你可以用于sudo
启动程序,但为了测试,将其切换到不同的端口号(例如 1502 或 50502)会更安全。
(通常 TCP 服务器首先以 root 身份启动,然后创建套接字,然后切换到非特权用户。ModbusServer 似乎不允许轻松完成此操作 - 它可能希望您以 root 身份运行整个程序。)