Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
02-03-2008, 12:41 AM
|
#1
|
|
Member
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75
Rep:
|
Help needed to understand a bit of shell script
Hi
Can someone explain the following piece of code from a small shell script (in particular, the one after $): -
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
Regards
|
|
|
|
02-03-2008, 01:32 AM
|
#2
|
|
Amigo developer
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,592
|
The variable $@ contains all the command line arguments passed to the program or function.
|
|
|
|
02-03-2008, 01:36 AM
|
#3
|
|
Member
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75
Original Poster
Rep:
|
Quote:
Originally Posted by gnashley
The variable $@ contains all the command line arguments passed to the program or function.
|
Thanks, but what does ${1+"$@"} as a whole do?
|
|
|
|
02-03-2008, 02:29 AM
|
#4
|
|
Moderator
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.4 OpenSuSE 12.2
Posts: 9,897
|
I have not truly clear the meaning of this particular line of code, but the syntax is
Code:
${parameter+alternative_value}
which means: if parameter is set, use alternative value, else use null string. In this case if argument number 1 is set, use all the argument list. But - I repeat - I cannot figure out what it means in this context.
|
|
|
|
02-03-2008, 04:00 AM
|
#5
|
|
Senior Member
Registered: Jul 2003
Location: Indiana
Distribution: Mandrake Slackware-current QNX4.25
Posts: 1,802
Rep:
|
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
This function is common in /etc/init.d/functions script.
The start_daemon function sometimes called daemon or startproc is responsible for starting the daemons, in this case it uses the program /sbin/start_daemon. It is passing the command line arguements ${1+"$@"} to /sbin/start_daemon. So you would pass the name of the daemon to the function, this becomes $1 and as was mentioned by gnashley $@ is the command line arguements passed to the script or function.
Example:So if you call the function like this
start_daemon
it will not work, but if you call it like this:
start_daemon cupsd --nice=0 --log=on
then this should work, you need to have at least 1 argv for it to work.
Normally return is used to pass error no's back from a function.
Last edited by /bin/bash; 02-03-2008 at 04:21 AM.
Reason: Un-obfuscate my comments :P
|
|
|
|
02-03-2008, 05:20 AM
|
#6
|
|
Moderator
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.4 OpenSuSE 12.2
Posts: 9,897
|
Thanks, but I still cannot figure out why simply "$@" couldn't be used in place of ${1+"$@"}.
|
|
|
|
02-03-2008, 06:43 AM
|
#7
|
|
Amigo developer
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,592
|
It seems to simply run /sbin/start_daemon with whatever arguments are passed. If at least one argument is given then all the arguments are passed. If no argument is given then none are passed. This would have done the same thing:
return /sbin/start_daemon "$@"
|
|
|
|
02-03-2008, 08:44 AM
|
#8
|
|
Member
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75
Original Poster
Rep:
|
Thanks.
Actually I'm trying to write an init script (derived from skeleton script provided by openSUSE 10.3). I'm also attaching the script.
This is the error I get while starting the service: -
Code:
Starting eSpyD /etc/init.d/eSpyD-service: line 70: return: /sbin/start_daemon: numeric argument required
failed
...and this is line 70:
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
...which is probably invoked from here:
Code:
start_daemon $ESPYD_BIN
Oops, attaching a file seems not possible, so here is complete script (I'm not removing comments): -
Code:
#!/bin/bash
#
# Implemented from template LSB system startup script for example
# service/daemon FOO
# Copyright (C) 1995--2005 Kurt Garloff, SUSE / Novell Inc.
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
# USA.
#
# /etc/init.d/eSpyD
#
# Note: This template uses functions rc_XXX defined in /etc/rc.status on
# UnitedLinux/SUSE/Novell based Linux distributions. However, it will work
# on other distributions as well, by using the LSB (Linux Standard Base)
# or RH functions or by open coding the needed functions.
# Read http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/ if you prefer not
# to use this template.
#
# chkconfig: 345 99 00
# description: eSpyD daemon which logs network usage for eSpy
#
### BEGIN INIT INFO
# Provides: eSpyD
# Required-Start:
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: eSpyD daemon which logs network usage for eSpy
# Description: Start eSpyD to allow logging of network usage which
# can be monitored with eSpy.
### END INIT INFO
#
ESPYD_BIN=/usr/local/sbin/eSpyD
test -x $ESPYD_BIN || { echo "$ESPYD_BIN not installed";
if [ "$1" = "stop" ]; then exit 0;
else exit 5; fi; }
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v be verbose in local rc status and clear it afterwards
# rc_status -v -r ditto and clear both the local and overall rc status
# rc_status -s display "skipped" and exit with status 3
# rc_status -u display "unused" and exit with status 3
# rc_failed set local and overall rc status to failed
# rc_failed <num> set local and overall rc status to <num>
# rc_reset clear both the local and overall rc status
# rc_exit exit appropriate to overall rc status
# rc_active checks whether a service is activated by symlinks
# Use the SUSE rc_ init script functions;
# emulate them on LSB, RH and other systems
# Default: Assume sysvinit binaries exist
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
killproc() { return /sbin/killproc ${1+"$@"}; }
pidofproc() { return /sbin/pidofproc ${1+"$@"}; }
checkproc() { return /sbin/checkproc ${1+"$@"}; }
if test -e /etc/rc.status; then
# SUSE rc script library
. /etc/rc.status
else
export LC_ALL=POSIX
_cmd=$1
declare -a _SMSG
if test "${_cmd}" = "status"; then
_SMSG=(running dead dead unused unknown reserved)
_RC_UNUSED=3
else
_SMSG=(done failed failed missed failed skipped unused failed failed reserved)
_RC_UNUSED=6
fi
if test -e /lib/lsb/init-functions; then
# LSB
. /lib/lsb/init-functions
echo_rc()
{
if test ${_RC_RV} = 0; then
log_success_msg " [${_SMSG[${_RC_RV}]}] "
else
log_failure_msg " [${_SMSG[${_RC_RV}]}] "
fi
}
# TODO: Add checking for lockfiles
checkproc() { return pidofproc ${1+"$@"} >/dev/null 2>&1; }
elif test -e /etc/init.d/functions; then
# RHAT
. /etc/init.d/functions
echo_rc()
{
#echo -n " [${_SMSG[${_RC_RV}]}] "
if test ${_RC_RV} = 0; then
success " [${_SMSG[${_RC_RV}]}] "
else
failure " [${_SMSG[${_RC_RV}]}] "
fi
}
checkproc() { return status ${1+"$@"}; }
start_daemon() { return daemon ${1+"$@"}; }
else
# emulate it
echo_rc() { echo " [${_SMSG[${_RC_RV}]}] "; }
fi
rc_reset() { _RC_RV=0; }
rc_failed()
{
if test -z "$1"; then
_RC_RV=1;
elif test "$1" != "0"; then
_RC_RV=$1;
fi
return ${_RC_RV}
}
rc_check()
{
return rc_failed $?
}
rc_status()
{
rc_failed $?
if test "$1" = "-r"; then _RC_RV=0; shift; fi
if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
if test "$1" = "-v"; then echo_rc; shift; fi
if test "$1" = "-r"; then _RC_RV=0; shift; fi
return ${_RC_RV}
}
rc_exit() { exit ${_RC_RV}; }
rc_active()
{
if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
return 1
}
fi
# Reset status of this service
rc_reset
# Return values acc. to LSB for all commands but status:
# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess argument(s)
# 3 - unimplemented feature (e.g. "reload")
# 4 - user had insufficient privileges
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running
# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signaling is not supported) are
# considered a success.
case "$1" in
start)
echo -n "Starting eSpyD "
## Start daemon with startproc(8). If this fails
## the return value is set appropriately by startproc.
start_daemon $ESPYD_BIN
# Remember status and be verbose
rc_status -v
;;
stop)
echo -n "Shutting down eSpyD "
## Stop daemon with killproc(8) and if this fails
## killproc sets the return value according to LSB.
killproc -TERM $ESPYD_BIN
# Remember status and be verbose
rc_status -v
;;
try-restart|condrestart)
## Do a restart only if the service was active before.
## Note: try-restart is now part of LSB (as of 1.9).
## RH has a similar command named condrestart.
if test "$1" = "condrestart"; then
echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
fi
$0 status
if test $? = 0; then
$0 restart
else
rc_reset # Not running is not a failure.
fi
# Remember status and be quiet
rc_status
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
$0 stop
$0 start
# Remember status and be quiet
rc_status
;;
force-reload)
## Signal the daemon to reload its config. Most daemons
## do this on signal 1 (SIGHUP).
## If it does not support it, restart the service if it
## is running.
echo -n "Reload service eSpyD "
$0 try-restart
rc_status -v
;;
reload)
## Like force-reload, but if daemon does not support
## signaling, do nothing (!)
echo -n "Reload service eSpyD "
rc_failed 3
rc_status -v
;;
status)
echo -n "Checking for service eSpyD "
## Check status with checkproc(8), if process is running
## checkproc will return with exit status 0.
# Return value is slightly different for the status command:
# 0 - service up and running
# 1 - service dead, but /var/run/ pid file exists
# 2 - service dead, but /var/lock/ lock file exists
# 3 - service not running (unused)
# 4 - service status unknown :-(
# 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
# NOTE: checkproc returns LSB compliant status values.
checkproc $FOO_BIN
# NOTE: rc_status knows that we called this init script with
# "status" option and adapts its messages accordingly.
rc_status -v
;;
probe)
# Don't do anything
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
exit 1
;;
esac
rc_exit
Do you have any idea about the reason for this error?
Thanks again,
|
|
|
|
02-03-2008, 12:05 PM
|
#9
|
|
Moderator
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.4 OpenSuSE 12.2
Posts: 9,897
|
Code:
# Default: Assume sysvinit binaries exist
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
killproc() { return /sbin/killproc ${1+"$@"}; }
pidofproc() { return /sbin/pidofproc ${1+"$@"}; }
checkproc() { return /sbin/checkproc ${1+"$@"}; }
This sounds like a bug to me. The return statement accepts a numeric argument not a command. You can try to simply remove return from the statements above: in this case the exit status of the last (and unique) command executed inside the function is returned.
Anyway, there is another skeleton in OpenSuSE 10.3 without this sysV init compatibility part: it is /etc/init.d/skeleton, instead of /etc/init.d/skeleton.compat. Have you tried that?
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 06:57 PM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|