Systemd

無法從以 systemd 啟動的程序訪問 USB 設備

  • September 11, 2019

我有以下腳本可以使用 GSM usb 調製解調器發送 SMS 消息:

#!/bin/bash

env > /home/hans/systemenv.txt
#touch /home/homeassistant/pipo2.txt
read count < /home/homeassistant/.homeassistant/smsCounter.txt

stty -F /dev/ttyUSB0 9600 min 100 time 2 -hupcl brkint ignpar -opost -onlcr -isig -icanon -echo

chat TIMEOUT 1 "" "AT+CMGF=1" "OK" > /dev/ttyUSB0
chat TIMEOUT 1 "" "AT+CMGS=\"0123456789\"" "OK" > /dev/ttyUSB0
chat TIMEOUT 1 "" "$1" "OK" > /dev/ttyUSB0
chat TIMEOUT 1 "" "^Z" "OK" > /dev/ttyUSB0

#sleep 2

#chat TIMEOUT 1 "" "AT+CMGS=\"0987654321\"" "OK" > /dev/ttyUSB0
#chat TIMEOUT 1 "" "$1" "OK" > /dev/ttyUSB0
#chat TIMEOUT 1 "" "^Z" "OK" > /dev/ttyUSB0

let 'count++'
echo $count > /home/homeassistant/.homeassistant/smsCounter.txt

從命令行呼叫該腳本時可以正常工作,但是當從使用 systemd 啟動的任何程序呼叫它時,腳本實際上會執行,但聊天命令不會被執行。執行 sudo journalctl -f -xe,當從 systemd 服務中執行的程序呼叫腳本時顯示以下內容:

Oct 08 13:37:37 homeassistant chat[2641]: Can't get terminal parameters: Inappropriate ioctl for device
Oct 08 13:37:37 homeassistant chat[2642]: Can't get terminal parameters: Inappropriate ioctl for device
Oct 08 13:37:37 homeassistant chat[2643]: Can't get terminal parameters: Inappropriate ioctl for device
Oct 08 13:37:37 homeassistant chat[2644]: Can't get terminal parameters: Inappropriate ioctl for device

在這種情況下,腳本是從一個名為 home assistant 的程序中呼叫的。家庭助理是從 systemd.service 腳本啟動的。如果我從終端啟動家庭助手,作為 systemd.service 執行的同一使用者,則上述內容不會顯示並且發送簡訊。

從使用 systemctl 啟動的任何其他程序呼叫相同的腳本會導致相同的錯誤。

這與 systemd 無關,也與程序systemctl的基本正確使用無關chat

chat是一個通常與 PPP 守護程序捆綁在一起的程序,至少從 1996 年開始,Al Longyear 維護的Linux PPP FAQ中已經回答了這個問題:

17.6。我跑了chat。它似乎想將本地終端用作調製解調器並且它不與調製解調器對話。如何指定調製解調器名稱chat

chat屬於一類稱為“過濾器”的程序。也就是說,它從標準輸入讀取,在內部進行一些處理,然後寫入標準輸出。

因此,如果您真的只想執行chat並讓它與調製解調器通信,那麼您需要使用 I/O 重定向運算符<>以便將標準輸入和輸出重定向到調製解調器。

但是,如果您使用chatwith pppd,請

$$ … $$

看看在做什麼:

聊天超時 1 "" "AT+CMGF=1" "OK" > /dev/ttyUSB0

您正在執行chat它的標準輸出連接到串列設備,但它的標準輸入連接到任何封閉的 shell 腳本的標準輸入。當您從互動式登錄會話執行 shell 腳本時,這將是終端,當您從守護程序執行 shell 腳本時,它將是守護程序的標準輸入,無論是什麼(幾乎肯定不會是終端字元設備)。

難怪chat不與串口設備聊天。難怪chat當您從守護程序執行 shell 腳本時,它甚至沒有與終端設備對話。

所以chat正確使用,正如Linux PPP FAQ所說。將其標準輸入和輸出設置為同一設備,即您嘗試與之通信的設備。

chat一旦您開始使用chat連接到正確的設備,您可能不想在所有這些多次呼叫中打開和關閉串列設備。同樣,這與 systemd 或守護程序無關,而是從具有共享標準標準輸入和輸出文件描述的 shell 執行多個連續命令的機制中的簡單練習。

或者,實際上,取決於它的作用,甚至以這種方式執行整個 shell 腳本,將整個腳本的標準輸入和輸出重定向到適當的設備,無論程序首先呼叫該腳本。(在這種情況下,使用-s選項以chat獲得最佳結果。)

該問題可能是由 SystemD 程序沒有(控制)終端引起的。

更好的解決方案是使用chat正確的 JdeBP 的答案,但對於一般情況……

您可以將此程式碼添加到腳本中:

tty &>/dev/null || exec </dev/tty

/dev/tty這將作為(控制)終端打開。

引用自:https://unix.stackexchange.com/questions/396832