I am currently trying to get DSL modem statistics into collectd, using a custom script called by the collectd-mod-exec. I fully understand that, to mitigate security concerns, collectd refuses to run scripts as root. However, this presents several problems:
In order to retrieve DSL statistics, or more specifically data from the DSL modem, I need to run the following (transcribed from /lib/functions/lantiq_dsl.sh):
(note: $XDSL_CTRL is either vdsl_cpe_control or, on older versions of OpenWrt, dsl_cpe_control, $@ is the actual command sent to the DSL modem.)
Now, when run as non-root user, this will obviously fail on several levels:
killall requires root to kill vdsl_cpe_control, so one could forego this in a good-faith assumption it is currently not running. Not great, but there's just no way to kill anything as non-root
lock /var/lock/dsl_pipe fails because /var/lock is only writeable to root. One could mitigate this to make /var/lock writeable to others. Again, not great.
but then, echoing to /tmp/pipe/dsl_cpe0_cmd will finally fail because this, again, is created by the root user and not writeable by others
(finally, even if one would chmod o+w /var/lock, lock -u on any lock there fails as user nobody and honestly, I have no idea why)
I am at a loss how all of this can be reformed so it would work as non-root user. The only way I see is to make an exception and ask collectd to run a script as root. Is there any way to do this?
Or does someone have another, better idea?
(I am thinking about running a cronjob as root that creates the collectd values on a regular basis, writes them to a temporary file, and just have the script called by collectd retrieve it, but that seems ... not so great.)
I would suggest rewriting your monitoring script in a language such as Lua that collectd has a loadable module for. I.e. avoid the exec plugin completely. Then your code will run as a part of collectd process, which runs as root, without any complaints.
@anon50098793: Thank you, so there is no way to run any script from exec as root (uid 0). At least it's a clear answer.
A sound suggestion, but I am really not familiar enough with LUA to pull that off
That's okay. I will go the cronjob route then. Honestly, I think getting the values "asynchronously" is not a bad idea anyway since retrieving values from the modem is rather costly, and doesn't need to happen very frequently.
I have collectd 5.4.1 running on openwrt 15.05 like this:
1985 root 16348 S /usr/sbin/collectd
1994 nobody 1496 S {coovachilli.sh} /bin/sh /usr/lib/collectd/coovachilli.sh
collectd running as root, started from /etc/init.d "old style". And then execs my custom script. So you might opt for using older version of collectd.
It's okay, I'm now doing it via a crontab into a temporary file that the exec script then just pipes back to collectd. Thank you for all your suggestions. "There is no (simple/non-workaround-ish) way" is a perfectly valid answer.
Quick follow-up question: Is there any public interest in what I concocted up for myself? Then I will upload the files into a Github Gist or something.
Note: "errors" and "errored seconds" are scaled up "per day" to deliver a somewhat informative scale. The collectd "DERIVE" data types normalizes into "per second", which does make sense if you want to display value changes on a time scale. But if you only receive two or three errors in a statistics period, that results into a scale that only displays decimal places which is of no use to anyone.
Yes, please! These look like useful monitoring data for marginal lines, It is so much nicer not having to resort to external tools for such monitoring...