Don't inappropriately use xargs to run rcorder -- xargs is designed
to run the given command as many times as necessary, but rcorder must be run just once, with all the rc.d scripts as args. If that turns out to be too many (E2BIG on exec) then we have more serious problems, working around it by use of xargs just makes a mess (for rcorder). Make the -e option cause the script to exit 0 if some enabled script was found, and 1 if not, so one can do: if service -e foobar >/dev/null then whatever we want to do when foobar is enabled else anything we want instead if it is not fi Someday perhaps add a -q to suppress the output instead of requiring the redirect, but that day is not this one. Make all error exit status codes be >1 (and use the standard 126 instead of 255, for "exec failed"). Note that with more than one service given with -e, or when none are (so all enabled scripts are listed) the exit status is 0 if any enabled script was found (ie: anything was printed to stdout), not if all named scripts exist and are enabled. Testing the status works best with just one script name given as an arg. Correctly quote script names (and use eval where required) so scripts (or paths to scripts) containing spaces, tabs, or shell operator chars might be handled correctly (newlines in names will still cause failures.) Treat rc.d scripts that do not have an rcvar (hence are always enabled) as enabled scripts, rather than disabled - but ignore the LOGIN DAEMON... pseudo-scripts. While here, replace archaic uses of "test" ('[') (that is, -a etc) with standard defined usages only, replace a baroque use of sed with sh code (which is simpler and much faster, not that speed matters) - but do use sed instead of two grep invocations. Replace all uses of "echo" with "printf" (just "because"!) Make the usage more useful (explain what the various option combinations achieve, explicitly), and also while here, make the formatting look closer to something I can deal with (personally I prefer tab indents almost everywhere, but 4 space is OK...) Aligned runs of 8 spaces were all replaced by a tab. For the options, use sh boolean cmds (true|false), and simply run them, rather than making them be empty or set and using test -n, it is easier to follow (and a tiny fraction of a ns faster). Change a comment so what it says is relevant to the code that is present, rather than to the change (referring to code that used to be present) with which it was added. Catch the manual page up with the minor parts of this intended to be visible to users (like the exit status change).
This commit is contained in:
parent
f1eb86a44f
commit
c6ec2ed896
|
@ -1,5 +1,5 @@
|
|||
#!/bin/sh
|
||||
# $NetBSD: service,v 1.8 2017/06/05 09:20:05 sborrill Exp $
|
||||
# $NetBSD: service,v 1.9 2023/03/14 06:19:35 kre Exp $
|
||||
# service -- run or list system services
|
||||
#
|
||||
# Taken from FreeBSD: releng/10.1/usr.sbin/service/service.sh 268098
|
||||
|
@ -34,93 +34,184 @@ export PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
|||
usage ()
|
||||
{
|
||||
local me="${0##*/}"
|
||||
echo "usage: ${me} [-elv]"
|
||||
echo " ${me} [-ev] rc_script_name [rc_script_name2 [...]]"
|
||||
echo " ${me} [-v] rc_script_name action"
|
||||
echo " -e: List enabled scripts; check if given scripts are enabled"
|
||||
echo " -l: List all scripts in rcorder"
|
||||
echo " -v: Verbose (mention in which directory script is found)"
|
||||
echo "rc_directories is currently set to ${rc_directories}"
|
||||
exit 1
|
||||
|
||||
exec >&2
|
||||
|
||||
printf 'Usage:\t%s -l [-v]\n' "${me}"
|
||||
printf '\t%s\n' \
|
||||
" List all scripts in rc order" \
|
||||
" -v: Prepend the value of rc_directories to the output" \
|
||||
"${me} -e [-v]" \
|
||||
" Print names of all enabled scripts" \
|
||||
" -v: Include the value of rc_directories (to stderr)" \
|
||||
"${me} -e [-v] rc_script_name [rc_script_name...]" \
|
||||
" Print path names of any given scripts which are enabled" \
|
||||
" -v: Include the value of rc_directories (to stderr)" \
|
||||
"${me} [-v] rc_script_name action" \
|
||||
" Run rc_script_name to perform the action specified" \
|
||||
" -v: Verbose (mention in which directory script was found)"
|
||||
printf 'rc_directories is currently set to: %s\n' "${rc_directories}"
|
||||
exit 2
|
||||
}
|
||||
|
||||
# list all files in rc_directories with absolute pathnames
|
||||
# written to be compatible with ls(1) from pre netbsd-7
|
||||
# (don't use ls(1) so we get the pathnames, without using non-std options)
|
||||
_rc_files()
|
||||
{
|
||||
local _d _f
|
||||
for _d in ${rc_directories}; do
|
||||
if [ -d "$_d" ]; then
|
||||
for _f in "$_d"/*; do
|
||||
[ -f "$_f" -a -x "$_f" ] && echo "$_f"
|
||||
done
|
||||
fi
|
||||
done | xargs rcorder -s nostart ${rc_rcorder_flags} 2>/dev/null
|
||||
local _d _f IFS
|
||||
|
||||
IFS=$'\n'
|
||||
rcorder -s nostart ${rc_rcorder_flags} $(
|
||||
for _d in ${rc_directories}
|
||||
do
|
||||
if [ -d "$_d" ]
|
||||
then
|
||||
for _f in "$_d"/*
|
||||
do
|
||||
if [ -f "$_f" ] && [ -x "$_f" ]
|
||||
then
|
||||
printf '%s\n' "$_f"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
while getopts elv o; do
|
||||
_rc_dirs()
|
||||
{
|
||||
if "${VERBOSE}"
|
||||
then
|
||||
printf 'rc_directories is %s\n' "${rc_directories}"
|
||||
fi
|
||||
}
|
||||
|
||||
ENABLED=false
|
||||
LIST=false
|
||||
VERBOSE=false
|
||||
|
||||
while getopts elv o
|
||||
do
|
||||
case "$o" in
|
||||
e) ENABLED=1 ;;
|
||||
l) LIST=1 ;;
|
||||
v) VERBOSE=1 ;;
|
||||
*) usage ;;
|
||||
e) ENABLED=true ;;
|
||||
l) LIST=true ;;
|
||||
v) VERBOSE=true ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
shift $(( OPTIND - 1 ))
|
||||
|
||||
[ -n "${ENABLED}" -a -n "${LIST}" ] && usage
|
||||
|
||||
. /etc/rc.subr
|
||||
load_rc_config :
|
||||
|
||||
if [ -n "${ENABLED}" ]; then
|
||||
[ -n "${VERBOSE}" ] && echo "rc_directories is ${rc_directories}" >&2
|
||||
flt=cat
|
||||
if [ $# -gt 0 ]
|
||||
then
|
||||
flt=$( echo $* | sed -e 's; ;|;g' -e 's;^;egrep /(;' -e 's;$;)$;' )
|
||||
fi
|
||||
_rc_files | $flt | while read file
|
||||
do
|
||||
if grep -q ^rcvar "$file"; then
|
||||
eval $( grep -m 1 ^name= "$file" )
|
||||
eval $( grep -m 1 ^rcvar "$file" )
|
||||
if [ -n "${rcvar}" ]; then
|
||||
load_rc_config ${rcvar}
|
||||
checkyesno ${rcvar} 2>/dev/null && echo ${file}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
if "${ENABLED}" && "${LIST}"
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ -n "${LIST}" ]; then
|
||||
[ -n "${VERBOSE}" ] && echo "rc_directories is ${rc_directories}" >&2
|
||||
if ! [ -f /etc/rc.subr ]
|
||||
then
|
||||
printf >&2 '%s: The rc system seems to be missing /etc/rc.subr\n' \
|
||||
"${0##*/}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if command . /etc/rc.subr
|
||||
then
|
||||
load_rc_config :
|
||||
else
|
||||
printf >&2 '%s: Problems running /etc/rc.subr. Aborting\n' "${0##*/}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if "${ENABLED}"
|
||||
then
|
||||
_rc_dirs >&2
|
||||
case $# in
|
||||
0) flt=cat;;
|
||||
*)
|
||||
IFS='|'
|
||||
flt="egrep '/(${*})\$'"
|
||||
;;
|
||||
esac
|
||||
if ( set +o pipefail ) 2>/dev/null
|
||||
then
|
||||
# If this option exists, disable it.
|
||||
set +o pipefail
|
||||
fi
|
||||
IFS=
|
||||
_rc_files | eval "$flt" |
|
||||
{
|
||||
found=false
|
||||
while read file
|
||||
do
|
||||
if grep -q '^rcvar=' "$file"
|
||||
then
|
||||
unset name rcvar
|
||||
eval "$( sed -n < "$file" -e '/^name=/p' -e '/^rcvar=/p' )"
|
||||
if [ -n "${rcvar}" ]
|
||||
then
|
||||
load_rc_config "${rcvar}"
|
||||
if checkyesno "${rcvar}" 2>/dev/null
|
||||
then
|
||||
printf '%s\n' "${file}"
|
||||
found=true
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# pseudo scripts like LOGIN DAEMON ... have no rcvar,
|
||||
# but aren't intended to be run either, those contain
|
||||
# no lower case letters in their names.
|
||||
#
|
||||
# Other scripts without an rcvar are always enabled
|
||||
#
|
||||
# So require at least one lower case letter in the name
|
||||
# in order to run a script without an rcvar, and include
|
||||
# them in the list of enabled scripts.
|
||||
|
||||
case "${file##*/}" in
|
||||
*[:lower:]*) printf '%s\n' "${file}"; found=true;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
"$found"
|
||||
}
|
||||
exit "$?"
|
||||
fi
|
||||
|
||||
if "${LIST}"
|
||||
then
|
||||
_rc_dirs
|
||||
_rc_files
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $# -eq 2 ]; then
|
||||
script=$1
|
||||
arg=$2
|
||||
else
|
||||
if [ "$#" -ne 2 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
|
||||
for dir in ${rc_directories}; do
|
||||
if [ -x "${dir}/${script}" ]; then
|
||||
[ -n "${VERBOSE}" ] && echo "${script} is located in ${dir}" >&2
|
||||
# run as in /etc/rc
|
||||
cd /
|
||||
umask 022
|
||||
exec env -i \
|
||||
HOME=/ PATH=/sbin:/bin:/usr/sbin:/usr/bin \
|
||||
"${dir}/${script}" "${arg}"
|
||||
echo "Failed to exec ${dir}/${script} ${arg}" >&2
|
||||
exit 255
|
||||
script=$1
|
||||
arg=$2
|
||||
|
||||
for dir in ${rc_directories}
|
||||
do
|
||||
if [ -x "${dir}/${script}" ]
|
||||
then
|
||||
if "${VERBOSE}"
|
||||
then
|
||||
printf >&2 '%s script is located in %s\n' "${script}" "${dir}"
|
||||
fi
|
||||
|
||||
# run as in /etc/rc
|
||||
cd /
|
||||
umask 022
|
||||
exec env -i \
|
||||
HOME=/ PATH=/sbin:/bin:/usr/sbin:/usr/bin \
|
||||
"${dir}/${script}" "${arg}"
|
||||
printf >&2 'Failed to exec %s (status %d)\n' \
|
||||
"${dir}/${script} ${arg}" "$?"
|
||||
exit 126
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${script} does not exist in ${rc_directories}" >&2
|
||||
printf >&2 '%s does not exist in%s\n' "${script}" "${rc_directories}"
|
||||
exit 1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: service.8,v 1.4 2015/04/02 18:41:22 ast Exp $
|
||||
.\" $NetBSD: service.8,v 1.5 2023/03/14 06:19:35 kre Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009 Douglas Barton
|
||||
.\" All rights reserved.
|
||||
|
@ -24,7 +24,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd March 20, 2015
|
||||
.Dd March 12, 2023
|
||||
.Dt SERVICE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -35,7 +35,7 @@
|
|||
.Op Fl elv
|
||||
.Nm
|
||||
.Op Fl ev
|
||||
.Ar rc_script_name1 Op Ar rc_script_name2 Op Ar ...
|
||||
.Ar rc_script_name Op Ar rc_script_name Ar ...
|
||||
.Nm
|
||||
.Op Fl v
|
||||
.Ar rc_script_name action
|
||||
|
@ -81,6 +81,9 @@ List all files in
|
|||
A script will be listed unless it has the
|
||||
.Qq nostart
|
||||
keyword enabled.
|
||||
Scripts are listed in the order the
|
||||
.EV rc.d
|
||||
system runs them at system boot time.
|
||||
.It Fl v
|
||||
Report what
|
||||
.Ev rc_directories
|
||||
|
@ -90,6 +93,13 @@ was found when an
|
|||
.Ar action
|
||||
is invoked.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fl e
|
||||
and
|
||||
.Fl l
|
||||
options are mutually exclusive.
|
||||
Only one of those may be used.
|
||||
.Sh ENVIRONMENT
|
||||
When used to invoke
|
||||
.Ev rc.d scripts, the
|
||||
|
@ -113,11 +123,23 @@ The
|
|||
is typically one of
|
||||
.Ar start ,
|
||||
.Ar restart ,
|
||||
or
|
||||
.Ar status ,
|
||||
or any other argument supported by the
|
||||
but can be any other argument supported by the
|
||||
.Fa rc_script_name .
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Nm
|
||||
exits with status 0 when successful,
|
||||
status 1 when
|
||||
.Fl e
|
||||
was given and no enabled script was found,
|
||||
or when an
|
||||
.Ar action
|
||||
is to be performed, but the
|
||||
.Ar rc_script_name
|
||||
given does not exist,
|
||||
or
|
||||
status >1 if another error occurs.
|
||||
.Sh EXAMPLES
|
||||
These are typical usages of the
|
||||
.Nm
|
||||
|
@ -133,6 +155,13 @@ inetd is located in /etc/rc.d
|
|||
inetd is running as pid 1713.
|
||||
.Ed
|
||||
.Bd -literal
|
||||
$ if service -e inetd >/dev/null; then echo inetd is enabled; fi
|
||||
inetd is enabled
|
||||
.Ed
|
||||
.Bd -literal
|
||||
$ if service -e foobar >/dev/null; then echo foobar is enabled; fi
|
||||
.Ed
|
||||
.Bd -literal
|
||||
$ service -ve ccd motd hostapd my_pkg
|
||||
rc_directories is /etc/rc.d /usr/pkg/etc/rc.d
|
||||
/etc/rc.d/ccd
|
||||
|
|
Loading…
Reference in New Issue