我正在嘗試使用 crontab 更改 Ubuntu 14.04 系統磁碟區。我正在使用以下命令:
pactl set-sink-volume 1 75%
當我在終端機中使用它或運行包含此命令的腳本時,它工作得很好,但是當系統從 crontab 或透過在 crontab 上運行的腳本運行此程式碼時,系統不會更改音量。我怎樣才能解決這個問題?
我也嘗試過
amixer -D pulse sset Master 75%
Crontab 看起來像(每分鐘用於測試目的)
* * * * * pactl set-sink-volume 1 75%
或者
* * * * * /usr/bin/pactl set-sink-volume 1 75\%
答案1
我花了一段時間才弄清楚,你可以這樣做:
1 9 * * * export DISPLAY=:0 && amixer -D pulse sset Master 48000
1 22 * * * export DISPLAY=:0 && amixer -D pulse sset Master 32000
100% 的音量約為 64000。
答案2
從...開始烏班圖19.10,一個簡單的DISPLAY=:0
(甚至0.0)在cron中沒有幫助,我得到了這個錯誤:
Connection failure: Connection refused
pa_context_connect() failed: Connection refused
我必須執行以下操作(這是我的夜間靜音cron,但您可以適應您的需要):
30 21 * * * bash -l -c "DISPLAY=:0.0 pactl --server unix:/run/user/$(id -u)/pulse/native set-sink-mute @DEFAULT_SINK@ on"
分解:
bash -l
用於登入外殼。DISPLAY=:0.0
用於展示--server unix:/run/user/$(id -u)/pulse/native
: (明確檔案描述符,因為 cron 不在登入 shell 中)@DEFAULT_SINK@ or 0
:預設或第一個音訊設備。對於特定設備,您可以使用完整的設備名稱,例如alsa_output.pci-0000_00_1f.3.analog-stereo
on
(或off
): 靜音開/關
我必須在 Ubuntu 19.10 中新增的部分是 arg --server
。
答案3
從 cron 運行命令
在許多情況下工作良好且可靠,但是當您需要或想要運行例如 GUI 應用程式時,或者在涉及環境變數的其他情況下,要找出如何正確設定 cron(組合)可能會非常困難工作,並找出哪個應該設定環境變數以及如何設定。
選擇
在這些情況下,有一個簡單的替代方案可以很方便,即在特定時間運行命令,甚至從當前使用者的環境中運行完整的「日間程式」。
這就是下面的腳本所做的事情。它運行命令和/或應用程序,以簡單格式列出在文字檔案中,如下所示:
11:09,gedit
11:10,gnome-terminal
11:20,pactl set-sink-volume 1 10%
我用你的命令測試了一下,效果很好。
如何設定
該安裝程式包含三個小文件,您需要將它們儲存在同一個資料夾中。在這些文件之一 ( command_data.txt
) 中,您需要列出命令以及您希望執行命令的時間,僅此而已。
使用以下格式:
time/comma/command (no spaces around the comma)
在 5 分鐘內將音量調至 100%,例如:
11:20,pactl set-sink-volume 1 0%
11:21,pactl set-sink-volume 1 20%
11:22,pactl set-sink-volume 1 40%
11:23,pactl set-sink-volume 1 60%
11:24,pactl set-sink-volume 1 80%
11:25,pactl set-sink-volume 1 100%
文件:
如前所述:這三個文件應位於同一個資料夾中。
文件1,主要腳本。
將其複製到空文件中,另存為schedule.py
(保持名稱不變)並使其可執行(重要)
#!/usr/bin/env python3
import subprocess
import time
import datetime
import os
cmd_data = os.path.dirname(os.path.abspath(__file__))+"/command_data.txt"
with open(cmd_data) as data:
s = [item.strip().split(",")+[None] for item in data.readlines()]
def currtime(set_time):
return int(set_time.split(":")[0])*60+int(set_time.split(":")[1])
def run_command(t, now, cmd, last_run):
if currtime(t) == now and last_run != int(time.strftime("%d%m%Y"))+int(now):
subprocess.Popen(["/bin/bash", "-c", cmd])
else:
pass
while True:
now = currtime(str(datetime.datetime.now().time())[:5])
for i in range(len(s)):
cmdata = s[i]
run_command(cmdata[0], now, cmdata[1], cmdata[2])
s[i][2] = int(time.strftime("%d%m%Y"))+int(now)
time.sleep(30)
文件 2,啟動/停止計畫的腳本。
將其另存為run_schedule.py
(保持名稱不變)並使其可執行(重要)
#!/usr/bin/env python3
import os
import subprocess
script_dir = os.path.dirname(os.path.abspath(__file__))
cmd = "ps -ef | grep schedule.py"
run = subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split("\n")
match = [line for line in run if script_dir+"/"+"schedule.py" in line]
if len(match) != 0:
subprocess.Popen(["kill", match[0].split()[1]])
subprocess.Popen(["notify-send", "Schedule stopped..."])
else:
subprocess.Popen(["/bin/bash", "-c", script_dir+"/"+"schedule.py"])
subprocess.Popen(["notify-send", "Schedule runs..."])
文件3、建立一個空文件,命名為command_data.txt
按照“如何設定”中的說明填寫您的命令
透過以下命令啟動/停止(切換)計劃:
/path/to/run_schedule.py
將出現一則通知訊息:
或者:
解釋
這些文件的作用:
當腳本schedule.py
啟動時,它會從 中讀取命令及其計劃的運行時間command_data.txt
。在循環中,將當前時間與列出的命令的計劃時間進行比較。如果目前時間等於一個或多個排程作業時間,則執行該指令並將目前時間標記為「完成」。
此腳本run_schedule.py
檢查主腳本 ( schedule.py
) 是否正在執行。如果是,則終止該作業,如果不是,則啟動該腳本。在這兩種情況下都會顯示確認通知。
答案4
這次真是萬分感謝。現在,當觸發 PIR 時,我的運動螢幕/音訊可以工作。
import time
import subprocess
from gpiozero import MotionSensor
import os
import logging
import time
import subprocess
os.environ["DISPLAY"] = ":0"
# Set up logging
logging.basicConfig(filename='output.log', level=logging.DEBUG,
format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
# Read in value of default_sink.txt for default_sink
with open('default_sink.txt', 'r') as f:
default_sink = f.read().strip()
print(default_sink)
# Constants
IR_SENSOR_PIN = 4 # GPIO pin number of IR sensor
TIMER_DURATION = 60 # Timer duration in seconds
# Initialize IR sensor and timer
ir_sensor = MotionSensor(IR_SENSOR_PIN)
timer = time.time() + TIMER_DURATION # Set timer to expire immediately
#run pactl command like this DISPLAY=:0.0 pactl --server unix:/run/user/1000/pulse/native set-sink-mute 0 on"
while True:
if ir_sensor.motion_detected:
logging.debug("Motion detected")
# Reset timer
timer = time.time() + TIMER_DURATION
# Turn on display and audio
subprocess.call("xset dpms force on", shell=True)
result = subprocess.run(f"DISPLAY=:0.0 pactl --server unix:/run/user/1000/pulse/native set-sink-mute '{default_sink}' 0", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with open("output.log", "a") as f:
f.write(result.stdout.decode())
f.write(result.stderr.decode())
f.write(f"Return code: {result.returncode}\n")
elif timer and time.time() > timer:
logging.debug("Timer expired")
# Turn off display and audio
subprocess.call("xset dpms force off", shell=True)
result = subprocess.run(f"DISPLAY=:0.0 pactl --server unix:/run/user/1000/pulse/native set-sink-mute '{default_sink}' 1", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with open("output.log", "a") as f:
f.write(result.stdout.decode())
f.write(result.stderr.decode())
f.write(f"Return code: {result.returncode}\n")
timer = time.time() + TIMER_DURATION # Set timer to expire immediately
time.sleep(1)