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.
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.
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.