I'm trying to run the command
sleepd --sleep-command "/usr/bin/apm -S" -u 900
to conserve some energy, by putting my computer in standby after 15 minute of idling. This command works fine when I type it at a tcsh or sh prompt, but now I want to run it at boot time.
The Debian booting structure is guiding me to do this via a distro-provided script, /etc/rc5.d/S20sleepd (a symlink to somewhere else, IIRC.) I've appended the full text of this script below, but I think the crucial bits are
#! /bin/sh
DAEMON=/usr/sbin/sleepd NAME=sleepd
PARAMS="" if [ -e /etc/default/sleepd ]; then . /etc/default/sleepd fi
case "$1" in start) start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON -- $PARAMS ;;
esac
exit 0
I'm supposed to set things up the way I like them by editing a line in /etc/default/sleepd that says PARAMS=something-or-other. I've tried various permutations, all of which give error messages, e.g.
PARAMS=--sleep-command "apm -S" -u 900
-> /etc/rc5.d/S20sleepd: apm -S: command not found
PARAMS='--sleep-command "apm -S" -u 900'
-> /usr/sbin/sleepd: invalid option -- S /usr/sbin/sleepd: invalid option -- "
PARAMS=--sleep-command apm -S -u 900
-> usage: apm [-VvmMsSd] [--verbose] [--minutes] [--monitor] [--suspend] [--standby]
I suspect the problems result from my poor understanding of how the Bourne shell handles quotes. Any ideas, please?
Here's the full script:
#! /bin/sh
DAEMON=/usr/sbin/sleepd NAME=sleepd DESC="APM sleep daemon"
test -f $DAEMON || exit 0
set -e
# Source defaults file; edit that file to configure this script. PARAMS="" if [ -e /etc/default/sleepd ]; then . /etc/default/sleepd fi
case "$1" in start) # Ensure apm module is loaded. test -e /dev/apm_bios && touch /dev/apm_bios
echo -n "Starting $DESC: " start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON -- $PARAMS echo "$NAME." ;; stop) echo -n "Stopping $DESC: " start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/$NAME.pid \ --exec $DAEMON -- $PARAMS echo "$NAME." ;; restart|force-reload) echo -n "Restarting $DESC: " start-stop-daemon --stop --quiet --oknodo --pidfile \ /var/run/$NAME.pid --exec $DAEMON -- $PARAMS sleep 1 start-stop-daemon --start --quiet --pidfile \ /var/run/$NAME.pid --exec $DAEMON -- $PARAMS echo "$NAME." ;; *) echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 exit 1 ;; esac
exit 0
Dan Hatton dan.hatton@btinternet.com wrote:
PARAMS='--sleep-command "apm -S" -u 900'
I suspect that PARAMS='--sleep-command apm\ -S -u 900' may do what you want, but I've not got a machine using sleepd to hand to try just now.
[...]
I suspect the problems result from my poor understanding of how the Bourne shell handles quotes. Any ideas, please?
Badly, IMO, and a major reason why I use the rc shell. It has a much simpler grammar.
Dan Hatton dan.hatton@btinternet.com writes:
I'm trying to run the command
sleepd --sleep-command "/usr/bin/apm -S" -u 900
to conserve some energy, by putting my computer in standby after 15 minute of idling. This command works fine when I type it at a tcsh or sh prompt, but now I want to run it at boot time.
The Debian booting structure is guiding me to do this via a distro-provided script, /etc/rc5.d/S20sleepd (a symlink to somewhere else, IIRC.) I've appended the full text of this script below, but I think the crucial bits are
#! /bin/sh
DAEMON=/usr/sbin/sleepd NAME=sleepd
PARAMS="" if [ -e /etc/default/sleepd ]; then . /etc/default/sleepd fi
case "$1" in start) start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --exec $DAEMON -- $PARAMS
The unquoted $PARAMS is being split into separate arguments _to start-stop-daemon_ on the whitespace it contains. There's nothing you can put in the value of PARAMS that will stop this. With this approach there is no way to write arguments that contain spaces as you need.
If you wrote "$PARAMS" then the internal spaces would be preserved, but you'd only be able to pass a single argument to start-stop-daemon (and thus to sleepd). Again there is nothing you can put in the value of PARAMS that will stop this.
In other words you can't easily write a fully general init script using an ordinary variable to carry the parameters (though evidently it hasn't stopped people trying).
You might be able to do something filthy using 'eval', but the reults would likely not be pretty.
My preferred approach would be to use the positional parameters to pass parameters to the daemon, for instance something like this untested(!) example:
#! /bin/sh set -e DAEMON="/usr/sbin/sleepd" NAME="sleepd" what="$1" set -- --sleep-command "/usr/bin/apm -S" -u 900 if [ -e /etc/default/sleepd ]; then . /etc/default/sleepd fi case "$what" in start ) start-stop-daemon --start --quiet --pidfile "/var/run/$NAME.pid" \ -exec "$DAEMON" -- "$@" ;; # ... etc etc etc ... esac
(Note that this would change the meaning of /etc/default/sleepd too.)
Richard Kettlewell rjk@terraraq.org.uk wrote:
The unquoted $PARAMS is being split into separate arguments _to start-stop-daemon_ on the whitespace it contains. There's nothing you can put in the value of PARAMS that will stop this. With this approach there is no way to write arguments that contain spaces as you need.
Ow. Does sh not have anything analogous to the list variable types found in csh and rc?
MJ Ray markj@cloaked.freeserve.co.uk writes:
Richard Kettlewell rjk@terraraq.org.uk wrote:
The unquoted $PARAMS is being split into separate arguments _to start-stop-daemon_ on the whitespace it contains. There's nothing you can put in the value of PARAMS that will stop this. With this approach there is no way to write arguments that contain spaces as you need.
Ow. Does sh not have anything analogous to the list variable types found in csh and rc?
bash does (see 'arrays') but /bin/sh in general does not.
Thanks for all the advice everyone. It led me to give up on using boot scripts, and get Login.app to to the job, and a couple of other things, via its /etc/X11/Login.app/Login.app.initcmd script. I added to the end of this script [1]:
if [ -x /usr/sbin/sleepd ]; then sleepd --sleep-command "xset dpms force off" -u 300 sleepd --sleep-command "hdparm -y /dev/hda" -u 600 sleepd --sleep-command "apm -S" -u 900 fi
The intention is to switch off the monitor when the system's been idle for 5 minutes, put the hard drive in standby after 10 minutes idle, and put the whole system in standby after 15 minutes. The ideas of using xset and hdparm came from http://www.imaclinux.net/gh.php?single=7.
This works, in the sense that it gets the required processes running, although so far, I've only had the patience to check that the monitor one does what I intended.
[1] This script is also in sh. Comments in one or two of the boot scripts suggest that they've been converted from bash to sh. I am prepared to speculate that this has been done to comply with some kind of standard, and that the standard in question could be Debian policy.
Dan Hatton dan.hatton@btinternet.com writes:
[1] This script is also in sh. Comments in one or two of the boot scripts suggest that they've been converted from bash to sh. I am prepared to speculate that this has been done to comply with some kind of standard, and that the standard in question could be Debian policy.
I'm not aware of anything in the Debian policy manual that says that scripts must use plain sh; indeed it quite clearly mentions the possibility of bash scripts (and reminds you to use the right #! line).
Avoiding gratuitous dependencies on particular shells can often be desirable, however.
On Mon, 9 Jun 2003, Richard Kettlewell wrote:
I'm not aware of anything in the Debian policy manual that says that scripts must use plain sh;
There doesn't seem to be anything that insists on sh for the init script itself, but for its configuration in /etc/default, which is what I was trying to edit, Debian Policy Manual section 10.3.2 says "It must contain only variable settings and comments in POSIX sh format."