purpose of run-parts(8) utility
You can use find
instead of run-parts
, there is no way to show which one is better. But I think using run-parts
is shorter (less typing) and make your script more maintainable. An example is /etc/crontab
:
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
For second question, you can find the answer in debianutils
source code. In file run-parts.c
, line 198:
/* Execute a file */
void run_part(char *progname)
{
....
args[0] = progname;
execv(progname, args);
error("failed to exec %s: %s", progname, strerror(errno));
exit(1);
....
}
You can see run-parts
using execv
system call. So if your file is not an binary execuable or an Interpreter script
, execv
can not run the file.
Note
- What is
Interpreter script
:
From man execve
, section Interpreter scripts
:
Interpreter scripts
An interpreter script is a text file that has execute permission
enabled and whose first line is of the form:
#! interpreter [optional-arg]
The interpreter must be a valid pathname for an executable which is not
itself a script. If the filename argument of execve() specifies an
interpreter script, then interpreter will be invoked with the following
arguments:
interpreter [optional-arg] filename arg...
where arg... is the series of words pointed to by the argv argument of
execve().
For portable use, optional-arg should either be absent, or be specified
as a single word (i.e., it should not contain white space); see NOTES
below.
- You can see debianutils source code here.
The files that run-parts
runs are fairly well documented. In addition to them being executable, the following man page snippet explains the requirements:
If neither the --lsbsysinit option nor the --regex option is given then the
names must consist entirely of ASCII upper- and lower-case letters, ASCII digits,
ASCII underscores, and ASCII minus-hyphens.
If the --lsbsysinit option is given, then the names must not end in .dpkg-old or
.dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong to one or more of the
following namespaces: the LANANA-assigned namespace (^[a-z0-9]+$); the LSB
hierarchical and reserved namespaces (^_?([a-z0-9_.]+-)+[a-z0-9]+$); and the
Debian cron script namespace (^[a-zA-Z0-9_-]+$)
Using the --lsbsysinit
option is particularly useful for running scripts in /etc
since many of the scripts will be listed as conffiles in their respective packages. A common case where files with the dpkg-*
extension are created is when changes have been made to the installed version and dpkg
tries to install a new version. dpkg
will usually store the version the user didn't choose in the same directory. Using run-parts
is a good, standard way to ensure that none of these extensions or any others which are not meant to be run aren't. It reduces the chances of bugs appearing because a developer forgot to include one of these in their script.
Even without the --lsbsysinit
, it is still a useful command to reduce the amount of code that needs to be written and improve reliability when used throughout the system. Though not quite so much as it is easier to replace with a find ... -executable -exec {} ;
or the like.