Shell 脚本手动可以工作但在 Crontab 中无法正常工作

Shell 脚本手动可以工作但在 Crontab 中无法正常工作

我有一个 Python 脚本,使用“subprocess”模块执行 ffmpeg 命令来录制音频/视频,如下所示:

def kill_ffmpeg_process(args):
    for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
        if proc.info['name'] == 'ffmpeg' and args in proc.info['cmdline']:
            print("found: " + str(proc))
            proc.kill()

kill_ffmpeg_process("ffmpeg")

rand_num = str(random.randint(0,99))
record_internal_cmd = f"ffmpeg -f pulse -ac 2 -i 'alsa_input.pci-0000_00_05.0.analog-stereo' -f v4l2 -i /dev/video4 -vcodec libx264 -crf 28 Desktop/recordings/{get_today_timestamp()}_{str(rand_num)}_internal_feed.mkv"
record_external_cmd = f"ffmpeg -f v4l2 -i /dev/video5 Desktop/recordings/{get_today_timestamp()}_{str(rand_num)}_external_feed.mkv"

print("Recording /dev/video4 with audio")
subprocess.Popen(record_internal_cmd,shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
time.sleep(1)
print("Recording /dev/video5")
subprocess.Popen(record_external_cmd,shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
time.sleep(3)

我想使用 crontab 安排此脚本每 1 小时(自动)执行一次,因此我创建了一个调用 Python 脚本的 .sh 文件#!/bin/bash python3 script.py。在终端中手动执行时,./shell_script.sh它可以正常工作,但将其添加到 crontab 时,它不起作用,因为它找不到音频源“个人想法”,因为当我从中删除录音时,它可以工作。但脉冲录音不起作用;它只执行第二条命令并创建包含视频录制的文件。

答案1

为什么会发生这种情况?

您的脚本显然需要运行 Pulse Audio...Pulse Audio 正在运行(自动地)作为用户服务...您可以使用以下命令查看服务的状态:

$ systemctl --user status pulseaudio
● pulseaudio.service - Sound Service
     Loaded: loaded (/usr/lib/systemd/user/pulseaudio.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-04-25 14:26:50 +03; 13min ago
TriggeredBy: ● pulseaudio.socket
   Main PID: 120691 (pulseaudio)
      Tasks: 4 (limit: 23594)
     Memory: 7.3M
        CPU: 389ms
     CGroup: /user.slice/user-1000.slice/[email protected]/session.slice/pulseaudio.service
             └─120691 /usr/bin/pulseaudio --daemonize=no --log-target=journal

Apr 25 14:26:50 Lenovo systemd[5211]: Starting Sound Service...
Apr 25 14:26:50 Lenovo systemd[5211]: Started Sound Service.

服务单元本身可以通过以下方式检查:

$ cat /usr/lib/systemd/user/pulseaudio.service
[Unit]
Description=Sound Service

# We require pulseaudio.socket to be active before starting the daemon, because
# while it is possible to use the service without the socket, it is not clear
# why it would be desirable.
#
# A user installing pulseaudio and doing `systemctl --user start pulseaudio`
# will not get the socket started, which might be confusing and problematic if
# the server is to be restarted later on, as the client autospawn feature
# might kick in. Also, a start of the socket unit will fail, adding to the
# confusion.
#
# After=pulseaudio.socket is not needed, as it is already implicit in the
# socket-service relationship, see systemd.socket(5).
Requires=pulseaudio.socket
ConditionUser=!root

[Service]
ExecStart=/usr/bin/pulseaudio --daemonize=no --log-target=journal
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
Restart=on-failure
RestrictNamespaces=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
# Note that notify will only work if --daemonize=no
Type=notify
UMask=0077
Slice=session.slice

[Install]
Also=pulseaudio.socket
WantedBy=default.target

查看三个重要的设置:

  1. WantedBy=default.target这意味着该服务不一定能一直使用到default.target启动过程中最后一个启用多用户的界面)。

  2. Requires=pulseaudio.socket仅在用户会话启动后可用(即登录后

  3. ConditionUser=!root也就是说,用户不能root

以上两者12在启动期间和登录之前,条件会影响正在运行的 Pulse Audio 守护程序是否可用于 crontab 作业。

健康)状况3root但是,即使登录后也不允许运行 Pulse Audio 守护程序。

该怎么办呢?

  • 您可以在用户的​​ crontab 中添加 cron 作业(Notroot的 crontab) 并确保您的用户在 cron 作业运行时已登录。

  • 您可以在脚本中手动运行 Pulse Audio 守护程序,以您明确指定的特定用户身份运行脚本,在这种情况下,甚至root可以使用...例如比较:

    $ sudo su root -c 'pacmd list-sources'
    No PulseAudio daemon running, or not running as session daemon.
    

    相对:

    $ sudo su root -c 'pulseaudio --start; pacmd list-sources'
    W: [pulseaudio] main.c: This program is not intended to be run as root (unless --system is specified).
    2 source(s) available.
         index: 0
         name: <alsa_output.pci-0000_00_1f.3.analog-stereo.monitor>
         driver: <module-alsa-card.c>
         flags: DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
         state: IDLE
         suspend cause: (none)
         priority: 1030
         volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
                 balance 0.00
         base volume: 65536 / 100% / 0.00 dB
         volume steps: 65537
         muted: no
         current latency: 0.00 ms
         max rewind: 344 KiB
         sample spec: s16le 2ch 44100Hz
         channel map: front-left,front-right
                      Stereo
         used by: 0
         linked by: 0
         configured latency: 2000.00 ms; range is 0.50 .. 2000.00 ms
         monitor_of: 0
         card: 0 <alsa_card.pci-0000_00_1f.3>
         module: 7
         properties:
             device.description = "Monitor of Built-in Audio Analogue Stereo"
             device.class = "monitor"
             alsa.card = "0"
             alsa.card_name = "HDA Intel PCH"
             alsa.long_card_name = "HDA Intel PCH at 0xa12a8000 irq 136"
             alsa.driver_name = "snd_hda_intel"
             device.bus_path = "pci-0000:00:1f.3"
             sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
             device.bus = "pci"
             device.vendor.id = "8086"
             device.vendor.name = "Intel Corporation"
             device.product.id = "9d71"
             device.product.name = "Sunrise Point-LP HD Audio"
             device.form_factor = "internal"
             device.string = "0"
             module-udev-detect.discovered = "1"
             device.icon_name = "audio-card-pci"
       * index: 1
         name: <alsa_input.pci-0000_00_1f.3.analog-stereo>
         driver: <module-alsa-card.c>
         flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
         state: IDLE
         suspend cause: (none)
         priority: 9039
         volume: front-left: 3381 /   5% / -77.25 dB,   front-right: 3381 /   5% / -77.25 dB
                 balance 0.00
         base volume: 6554 /  10% / -60.00 dB
         volume steps: 65537
         muted: yes
         current latency: 353.71 ms
         max rewind: 0 KiB
         sample spec: s16le 2ch 44100Hz
         channel map: front-left,front-right
                      Stereo
         used by: 0
         linked by: 0
         configured latency: 2000.00 ms; range is 0.50 .. 2000.00 ms
         card: 0 <alsa_card.pci-0000_00_1f.3>
         module: 7
         properties:
             alsa.resolution_bits = "16"
             device.api = "alsa"
             device.class = "sound"
             alsa.class = "generic"
             alsa.subclass = "generic-mix"
             alsa.name = "ALC236 Analog"
             alsa.id = "ALC236 Analog"
             alsa.subdevice = "0"
             alsa.subdevice_name = "subdevice #0"
             alsa.device = "0"
             alsa.card = "0"
             alsa.card_name = "HDA Intel PCH"
             alsa.long_card_name = "HDA Intel PCH at 0xa12a8000 irq 136"
             alsa.driver_name = "snd_hda_intel"
             device.bus_path = "pci-0000:00:1f.3"
             sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
             device.bus = "pci"
             device.vendor.id = "8086"
             device.vendor.name = "Intel Corporation"
             device.product.id = "9d71"
             device.product.name = "Sunrise Point-LP HD Audio"
             device.form_factor = "internal"
             device.string = "front:0"
             device.buffering.buffer_size = "352800"
             device.buffering.fragment_size = "176400"
             device.access_mode = "mmap+timer"
             device.profile.name = "analog-stereo"
             device.profile.description = "Analogue Stereo"
             device.description = "Built-in Audio Analogue Stereo"
             module-udev-detect.discovered = "1"
             device.icon_name = "audio-card-pci"
         ports:
             analog-input-internal-mic: Internal Microphone (priority 8900, latency offset 0 usec, available: unknown)
                 properties:
                     device.icon_name = "audio-input-microphone"
             analog-input-mic: Microphone (priority 8700, latency offset 0 usec, available: no)
                 properties:
                     device.icon_name = "audio-input-microphone"
         active port: <analog-input-internal-mic>
    
  • 你可以运行 Pulse Audio 作为系统范围的守护进程

相关内容