1

I am new to scripts and daemons and, after toying for a while, find myself stuck.

Here is the situation: on macos, I have a program called "maza" which updates my hosts file using online blocklists. I want to run this program, say, once a week to keep up with changes in blocklists. After trying my luck with cronjobs (which didn't work), I am now trying with a daemon. So I have:

  • One file called com.mazaupdate.plist located in /Library/LaunchDaemons
  • One script called scriptmaza.sh located in /etc (since this is where the hosts file is)

My plist says the following (basically it seeks to launch the script - at this point every 60 seconds, for testing purposes).

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.mazaupdate</string>
    <key>ProgramArguments</key>
    <array>
        <string>/etc/scriptmaza.sh</string>
    </array>
    <key>StartInterval</key> 
        <integer>60</integer>
</dict>
</plist>

And my script says the following (it just stops maza, which is easier to test than "update" because there are currently no online updates to be made to the hosts file).

#!/bin/sh
sudo maza stop

Once the testing is over,the plist will be amended to launch the script every week only, and the script will be updated to read "maza update".

With my two files in place, I do:

sudo chown root /Library/LaunchDaemons/com.mazaupdate.plist 
sudo chgrp wheel /Library/LaunchDaemons/com.mazaupdate.plist

and

sudo launchctl load com.mazaupdate.plist 

However, when I test the status of maza after a few minutes, it always says "enabled", meaning the stop command is not properly used. Of course, if I just use "sudo maza stop" in the terminal, maza properly stops and the status becomes "disabled", which ought to be the case if the script worked.

That's about all I have. Any idea? Thanks! Ken

EDIT:

Following comments by @pmdj below, here is where we stand.

After a chmod +x on scriptmaza.sh, permissions are: -rwxr-xr-x@ 1 ken wheel 80 17 Feb 12:22 /etc/scriptmaza.sh

The revised scriptmaza.sh is now:

#!/bin/sh
/usr/local/bin/maza stop
date >> /Users/Ken/Downloads/file.dat

After loading the daemon for a little while, file.dat does get created and edited every minute with the proper date, meaning the daemon does launch the script.

The console shows the daemon being loaded and unloaded properly, and the scriptmaza log a number of lines saying "tput: No value for $TERM and no -T specified"

Meanwhile, the status of maza remains "enabled".

EDIT2: maza author says "No, there is no flag because it is not necessary. I can confirm that it runs as a daemon because that's how it works on my computer. There is nothing in the script that you can't run line by line from a terminal. If you want to know what is happening, a first step would be to open it and run each line. Good luck!" Does this help?

EDIT3: removed the 'tput' elements for colours. The daemon still successfully launches mazascript, which successfully adds the date to the specially-created file.dat. However, maza is not actually stopped, as it should in the script (which, when it works, will be replaced with 'update'). The log now gives a new error, saying "ERROR. You must install gsed if you are using OSX". This error does not occur when launching maza manually, and gsed is already installed ("brew install gnu-sed" gives "gnu-sed 4.8 is already installed and up-to-date. To re-install.....". An alias for Gsed is found in "/usr/local/bin". The relevant part of maza (testing gsed) is the following:

custom-sed() {
    if [[ $THIS_OS = *$NAME_OSX* ]]; then
        # Check if OSX and install GSED
        if [ -x "$(command -v gsed)" ]; then
            gsed "$@"
        else
            echo "${COLOR_RED}ERROR. You must install gsed if you are using OSX${COLOR_RESET}"
            exit 1
        fi
    else
        # Linux
        sed "$@"
    fi
}
export -f custom-sed

EDIT4: here are the relevant parts; first the variables, then the update/start functions.

# VARIABLES
NAME_OSX="Darwin"
THIS_OS=$(uname -mrs)
PROGNAME=$(basename $0)
[[ -z "${XDG_CONFIG_HOME}" ]] && CONFIG=$HOME/.maza/ || CONFIG=$XDG_CONFIG_HOME/maza
HOST_FILE=(/etc/hosts)
COLOR_RED=""
COLOR_GREEN=""
COLOR_RESET=""
LIST="list"
LIST_DNSMASQ="dnsmasq.conf"
START_TAG="## MAZA - List ad blocking"
PROJECT="### https://github.com/tanrax/maza-ad-blocking"
AUTHOR="### Created by Andros Fenollosa (https://programadorwebvalencia.com/)"
END_TAG="## END MAZA"
PATH=$PATH:/usr/local/bin
update() {
    # Make conf folder
    rm -f $CONFIG$LIST
    rm -f $CONFIG$LIST_DNSMASQ
    mkdir -p $CONFIG
    # Download DNS list
    curl -L -s "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" -o "$CONFIG$LIST"
    # Clear list
    ## Remove comments
    # custom-sed -i.bak '/^#/ d' "$CONFIG$LIST"
    # Make dnsmasq format
    ## 127.0.0.1 doubleclick.net to address=/doubleclick.net/127.0.0.1
    cp "$CONFIG$LIST" "$CONFIG$LIST_DNSMASQ"
    custom-sed -i.bak 's/127.0.0.1 /address=\//g' "$CONFIG$LIST_DNSMASQ"
    custom-sed -i.bak 's/$/\/127.0.0.1/g' "$CONFIG$LIST_DNSMASQ"
    ## Add start tag DNS list in first line
    custom-sed -i.bak "1i\\$AUTHOR" "$CONFIG$LIST"
    custom-sed -i.bak "1i\\$PROJECT" "$CONFIG$LIST"
    custom-sed -i.bak "1i\\$START_TAG" "$CONFIG$LIST"
    ## Add end tag DNS list in first line
    echo $END_TAG >> "$CONFIG/$LIST"
    ## Add start tag DNS dnsmasq in first line
    custom-sed -i.bak "1i\\$AUTHOR" "$CONFIG$LIST_DNSMASQ"
    custom-sed -i.bak "1i\\$PROJECT" "$CONFIG$LIST_DNSMASQ"
    custom-sed -i.bak "1i\\$START_TAG" "$CONFIG$LIST_DNSMASQ"
    ## Add end tag DNS DNSMASQ in first line
    echo $END_TAG >> "$CONFIG$LIST_DNSMASQ"
    # Remove temp file
    rm "$CONFIG$LIST.bak"
    rm "$CONFIG$LIST_DNSMASQ.bak"
    # Notify user
    echo "${COLOR_GREEN}List updated!${COLOR_RESET}"
}

start() {
    update
    # Add List to host file
    cat "$CONFIG/$LIST" >> "$HOST_FILE"
    # Notify user
    echo "${COLOR_GREEN}ENABLED!${COLOR_RESET}"
}
KenMatsuo
  • 11
  • 3
  • It sounds like the remaining problems are specific to `maza` - I am unfortunately not familiar with this software, so I don't have a specific idea on how to solve it. The error `tput: No value for $TERM and no -T specified` makes it sound like (a) `maza` is a shell script itself and (b) it is written assuming that the command will be run from a terminal window, not in the background. Is there a command line flag you can pass to it to use it as part of a non-terminal invocation? – pmdj Feb 27 '22 at 09:29
  • Maza is indeed a shell script. Unfortunately, I am not sure what difference this should make in the script. Here is the maza Github repository: https://github.com/tanrax/maza-ad-blocking PS: options for maza seem to be limited to start, stop, update and status. – KenMatsuo Mar 07 '22 at 16:01
  • Just edited the original post with a response from the author of maza. @pmdj – KenMatsuo Mar 11 '22 at 13:12
  • Would be really useful to get some feedback, if possible. Seems we're really close! @pmdj – KenMatsuo Mar 16 '22 at 08:31
  • Presumably the maza author is not running this as a daemon **on macOS**? Anyway, I'm not an expert on shell scripting and virtual terminals, but I'd probably try following the error and remove the use of `tput`, as it seems to just be for colouring output. Try modifying these lines: ``COLOR_RED=`tput setaf 1` `` -> `COLOR_RED=""` (same for green & reset) and see if that solves the problem for you. If it does, then perhaps you could submit a patch that conditionally sets either the original values or blank ones depending on whether `"$TERM"` is empty. – pmdj Mar 16 '22 at 09:45
  • Thanks a lot, @pmdj. I just updated the text above (see "EDIT3" in the post) with the results. Long story short: there is now an error relating to gsed, which does not happen when maza is launched manually, and despite gsed actually being installed already. – KenMatsuo Mar 16 '22 at 12:07
  • This seems like a PATH issue. Might want to add /usr/local/bin to the PATH from your wrapper script. – pmdj Mar 16 '22 at 12:13
  • @pmdj, sure, but.... where? sorry, I'm still really new to this. If you mean my own tiny scriptmaza.sh, it's already there (see above). If you mean in maza itself, where? before gsed in the part that I copied? – KenMatsuo Mar 16 '22 at 15:54
  • Hey @pmdj, following up on the question above. what's the wrapper script? is that my scriptmaza.sh? If so, then /usr/local/bin is already there, as shown in the code above. – KenMatsuo Mar 30 '22 at 07:56
  • Hmm, I don't see anywhere where you've added something along the lines of `PATH=$PATH:/usr/local/bin` before invoking `maza`. Are you saying you have that? The line with `command` will not find `gsed` unless it's located in one of the directories listed in the `PATH` environment variable, so I assumed that was what was going wrong. – pmdj Mar 30 '22 at 08:02
  • Hey @pmdj, just saw your comment this morning. Indeed that helped and I found the way to do it :) I think we're super close now. There is one more error, but it's not a problem with maza itself. I get the following issue: "mkdir: /.maza: Read-only file system". Seems linked to macos' SIP. Is the solution to move maza somewhere else? I tried to move it to my download folder but that didn't help. – KenMatsuo Mar 31 '22 at 15:20
  • Seems like it's trying to put stuff in the user's home directory, but the root user doesn't have one on macOS and instead inherits it from the parent process, or defaults to `/`, which in turn is indeed read-only. Is there a way to specify the directory where `maza` keeps its data? – pmdj Mar 31 '22 at 20:03
  • Not sure. Let me add the code in question in the main text of the post. To be clear, the reason is encounters this error now and not before is because, for testing purposes, scriptmaza.sh only stopped maza. When that worked, I asked instead to start maza, and that's when mkdir is used (well, as part of the update). – KenMatsuo Mar 31 '22 at 20:34

1 Answers1

0

This started out as a comment but got out of hand.

Here's an incomplete list of what I'd check and try if I was troubleshooting this:

  1. What are the permissions on the script? Is it executable? (what does ls -l /etc/scriptmaza.sh say?)
  2. Is the maza executable in the root user's default $PATH?
  3. Are you seeing anything relevant in the system log?
  4. Have you tried logging any output and errors from your script? Add something like this to your launchd plist:
    <key>StandardOutPath</key>
    <string>/var/log/scriptmaza.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/scriptmaza.log</string>
  1. Have you tried adding any other side effects to your script you can use as evidence for checking whether or not your script is running at all, for example an echo command or date (If not logging stdout/stderr, you'll need to explicitly write to a file using >> /var/log/scriptmaza.log or so)

(FWIW, /etc/ isn't a great spot for executable scripts, but it shouldn't prevent things from working. You also don't need sudo in the script as it'll run as root anyway, and if it didn't, there's no interactive console for entering a password anyway.)

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Thanks for the detailed reply @pmdj. Here is what I can add. 1. I did a chmod +x on the script, which I had not done before. Permissions are now as follows: -rwxr-xr-x@ 1 ken wheel 80 17 Feb 12:22 /etc/scriptmaza.sh 2. the maza executable is in /usr/local/bin; I guess that's the default? I have just added the path in the script, although if it's already the default, it shouldn't change anything 3. from what I can see, there is not much in the system log, no. – KenMatsuo Feb 17 '22 at 11:41
  • 4. I added the log for scriptmaza.sh, as you recommended and, at some point, I got an error saying "maza: command not found", but I can no longer replicate it, so maybe adding the path (cf. point 2) solved that. 5. I just added "date >> /Users/Ken/Downloads/file.dat" and this works every time I launch the script myself ("sudo /etc/scriptmaza.sh") just like maza is actually disabled when I do this. So it seems like the script works properly when it is launched directly, but when I load the daemon, nothing happens, so the script seems not to be launched. – KenMatsuo Feb 17 '22 at 11:41
  • Correction! The file.dat is edited every minute when the daemon is loaded. Which means that the daemon does successfully launch the script. However, it is not actually stopping maza. Can it be that it doesn't have the right permissions? – KenMatsuo Feb 17 '22 at 11:44
  • Can you update your question with the latest version of the script and the log output? I've lost track a little. If it's running the command but is encountering some kind of failure in the process, there should be an error logged? – pmdj Feb 18 '22 at 14:56