3

I posted this in Raspberry Pi, but was told that it was better suited in a general linux or programming area. So I figured I'd ask here now...

I am putting together a kiosk that should play video. I'm using a NUC with Raspberry Pi Desktop. Everything works but automating the audio with Cron. I work in a school and blasting sound during the day would kind of suck, so I want it to change based on the time of the day.

When run from terminal the following code works:

/usr/bin/amixer set Master 16384

and

amixer sset 'Master' 16384

So, I put it into Cron:

15 09 * * * /usr/bin/amixer set Master 16384

and

43 09 * * * amixer sset 'Master' 16384

Nothing. Fine. So I make a really simple python script to run (yes, I realize I put it in a system folder, I was planning on moving it, it just kind of ended up there.)

#!/usr/bin/env python3

from subprocess import call
call(["/usr/bin/amixer", "set", "Master", "65536"])

I make it executable:

chmod +x /etc/python/sound100.py

Then I call it from the terminal with both:

/etc/python/sound100.py

and

/usr/bin/python3 /etc/python/sound100.py

Again, it works. Yay. Into Cron it goes. Neither:

11 10 * * * python3 /etc/python/sound100.py

nor

11 10 * * * /usr/bin/python3 /etc/python/sound100.py

Not even

11 10 * * * /etc/python/sound100.py

Nothing works.

So begins the actual troubleshooting. I check the syslog. Everything runs, but I learn that when I run it as a sudo command it says that the maximum volume is 83 when run as a sudoer. So that means I can't run it as from sudo crontab -e, but I start running it from the user's cron.

Still nothing. So I try running it as a sudoer but with the user beforehand. Nothing again.

Please help me. I just want to adjust the volume automatically without logging into ssh for every NUC we're putting up three times a day until I quit or retire.

Thank you!

7
  • 1
    Whose crontab is this? Is the user logged in when the cron is supposed to run?
    – terdon
    Oct 11, 2021 at 17:22
  • I've done both. I've run crontab -e as sudo and as the user. I also tried to run the command from sudo as the specific user. None of it worked.
    – kstthomsen
    Oct 11, 2021 at 17:24
  • 1
    The first thing to try is to capture any errors. Change the cron line to 15 09 * * * /usr/bin/amixer set Master 16384 2>/tmp/cronVolumeLog and then check if there are any contents in /tmp/cronVolumeLog. I suspect cron can't do this, it might need access to environment variables it won't have, but that might help us narrow down the issue.
    – terdon
    Oct 11, 2021 at 17:37
  • Nothing's populating in cronVolumeLog, but I know it's running through syslog: Oct 11 11:27:01 hubentrykiosk CRON[1886]: (pi) CMD (/usr/bin/amixer set Master 16384 2>/tmp/cronVolumeLog) Will it generate information even if it runs correctly? Or am I missing something?
    – kstthomsen
    Oct 11, 2021 at 18:30
  • 1
    The PPID is just the parent process ID; not important. The SHELL is the source of your issue. Try editing the crontab as the answer suggests, setting the SHELL environment variable. Oct 12, 2021 at 16:13

4 Answers 4

2

After all the help I received I was ultimately able to find a solution. It's not the solution I really wanted and it's not very clean, but it works so I'm posting it here.

The Issue as I Understand it

The heart of the problem seems to be that running Amixer as a generic user elevates to a Sudo permission no matter what I do, and making another user just to run the audio Cronjobs didn't work.

This resulted in every amixer command sent manually via terminal to adjust the volume to a max of 65536 and every command sent via Cron to max out at 88. This huge disparity resulted in effectively muting the audio no matter what I did.

Thanks to a lot of help from the two folks here I've come to the conclusion that it's likely because one is trying to run bash and the other is running sh. But getting the two to reconcile seems to be impossible.

I have ultimately given up and have completely changed how I'm running the physical components all together...

So, here's my solution:

After switching to an HDMI to AGP adapter I plugged in a simple 3.5mm male-to-male audio jack from the NUC to the TV. The TV I'm using allows video from AGP and audio from 3.5mm, so now I have video to the TV, but Audio needed to be switched to Stereo Output on the NUC to get it to work.

After this I ran amixer scontents and sudo amixer scontents and went through the information. Master displayed the two separate values as I came to expect, but PCM now showed 255, which it did not previously.

With this in mind I changed my focus from Master to PCM, and updated the Crontab with the following:

40 06 * * 1-5 amixer sset 'PCM' 191 2> /tmp/cronVolumeLog

25 07 * * 1-5 amixer sset 'PCM' 64 2> /tmp/cronVolumeLog

40 14 * * 1-5 amixer sset 'PCM' 128 2> /tmp/cronVolumeLog

Everything is now working the way that I expected, though with some crackling and other minor issues that appear with using an audio jack, but I'll just have to deal with them.

I know that this isn't the most honest answer to the problem, but it's the only one I found that worked for me after (literally) days worth of searching and working with anyone willing to help me.

My hope is that someone, sometime, will see this post and get a little farther than I did and find a solution. Or give up quickly and move on with their lives and be happy with the stupid audio jack.

But I learned a lot, so that's something.

1

I'm not in a place where I can test this, but a frequent cause of failures in cron of the type you've described is the differences in the environment. You can see this easily if you run printenv from the command line, and compare that output to printenv that you run as a cron job. For example:

* * * * * /path/to/printenv > /home/pi/cron_env.txt 2>&1 

You'll see many differences in the two outputs. You may be able to pick through the list, and identify the environment variable that's creating the problem - I recall that RPi OS creates special groups for some audio & bluetooth functions, but I can't recall them from memory.

Assuming you are using bash as the shell from which you entered your commands, an easier approach to this may be to invoke bash -l to run the commands in crontab:

15 09 * * * bash -l /usr/bin/amixer set Master 16384 
43 09 * * * bash -l /usr/bin/amixer sset 'Master' 16384

And, as suggested in the comments, it's always a good idea to capture any stderr output in a file with a redirect following the amixer commands:

15 09 * * * bash -l /usr/bin/amixer set Master 16384 2> /home/pi/cronErrorLog.txt 
6
  • I'm understanding this a little more. When I place SHELL=/bin/bash before the cronjob line it allows me to save it, but it errors when I enter source /home/pi/.profile below the shell line. The error says 'bad minute errors in crontab file'.
    – kstthomsen
    Oct 12, 2021 at 16:44
  • There may be something else going on here and it may have to do with the source issue, which looks like I'm trying to call the cronjob as the 'pi' user. When I look at the log it outputs the shell as bin/bash now, which is good, but the playback volume is only changing to 87, not 16384 which is effectively muted. This was happening when I ran the amixer command as sudo, but doesn't happen when run as Pi. However, the cronjob is being entered into pi's crontab and shouldn't be running as sudo...correct?
    – kstthomsen
    Oct 12, 2021 at 16:51
  • I was able to get the source line to work with SOURCE=/home/pi/.profile which I hope was what you meant. It looks like it's working now as the log outputs that as an `X-Cron-Env'. But it's not fixing the audio-only going to 87 and not 16384. This may be an issue outside of cron now, but suggestions would be welcome. It works from the terminal so it may still work from cron.
    – kstthomsen
    Oct 12, 2021 at 17:12
  • @kstthomsen: source is a built-in command in bash - it simply means "read and execute the contents of the file named in the argument", and it is not invoked with source= - it's just source <file argument>. Correct: If you put the command into user pi's crontab, it runs with pi's privileges - not sudo. I've made an edit to my answer - please try this & let us know the result.
    – Seamus
    Oct 12, 2021 at 21:58
  • I tried what you've updated your answer to, and it generates the following error /usr/bin/amixer: /usr/bin/amixer: cannot execute binary file. I can't find a suggestion online that seems relevant to fix it. (As an aside, thank you so much for helping me!)
    – kstthomsen
    Oct 13, 2021 at 19:27
1

Running amixer via cron is done as the sudo user as the OP expanded on. What I found is that instead of 'Master' you will have 'Headphone' or similar which does control the AV output. Instead of fiddling with the raw values for volume level just use a percentage to set the volume to the desired level. i.e.

15 09 * * * /usr/bin/amixer set Master 100\%

Note: The percent sign is escaped in the above example.

0

my solution is

* * * * * export XDG_RUNTIME_DIR=/run/user/1000 && /usr/bin/amixer -D pulse sset Master 50\%

in my environment it seems XDG_RUNTIME_DIR needed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .