crontab을 사용하여 Ubuntu 14.04 시스템 볼륨을 변경하려고 합니다. 다음 명령을 사용하고 있습니다.
pactl set-sink-volume 1 75%
터미널에서 사용하거나 이 명령이 포함된 스크립트를 실행하면 제대로 작동하지만 시스템이 crontab에서 또는 crontab에서 실행되는 스크립트를 통해 이 코드를 실행하면 시스템이 볼륨을 변경하지 않습니다. 이 문제를 어떻게 해결할 수 있나요?
나는 또한 시도했다
amixer -D pulse sset Master 75%
Crontab은 다음과 같습니다(테스트 목적으로 1분마다).
* * * * * 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입니다. 그러면 볼륨이 9로 올라가고 22로 작아집니다. 또한 sudo가 아닌 사용자 crontab에서도 마찬가지입니다.
답변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이 로그인 쉘에 없기 때문에 명시적인 파일 설명자)@DEFAULT_SINK@ or 0
: 기본 또는 첫 번째 오디오 장치입니다. 특정 장치의 경우 전체 장치 이름을 사용할 수 있습니다. 예:alsa_output.pci-0000_00_1f.3.analog-stereo
on
(또는off
): 음소거 켜기/끄기
Ubuntu 19.10에 추가해야 했던 부분은 --server
arg였습니다.
답변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)