[arch-projects] [INITSCRIPTS][PATCH 1/6] Using bash built-in cat and case to avoid grep run
From: Igor M Podlesny <for.poige+archlinux@gmail.com> Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.sysinit | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 58f3216..c276da7 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -42,9 +42,10 @@ if [[ ! -a /usr/lib ]] ; then printf "${C_FAIL}/usr is not mounted. This is not supported.${C_OTHER}\n" fi -if ! grep -q devtmpfs /proc/filesystems; then - printf "${C_FAIL}Your kernel does not have devtmpfs support. This is not supported.${C_OTHER}\n" -fi +case $(< /proc/filesystems) in + *devtmpfs*) ;; + *) printf "${C_FAIL}Your kernel does not have devtmpfs support. This is not supported.${C_OTHER}\n" ;; +esac HWCLOCK_PARAMS="--systz" case $HARDWARECLOCK in -- Sebastien "Seblu" Luttringer
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKGBUILD b/PKGBUILD index 6186de5..0c63e59 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -10,7 +10,7 @@ conflicts=('initscripts') provides=('initscripts=9999') backup=(etc/inittab etc/rc.conf etc/rc.local etc/rc.local.shutdown) makedepends=('asciidoc') -depends=('glibc' 'bash' 'grep' 'coreutils' 'systemd-tools' 'iproute2' +depends=('glibc' 'bash' 'coreutils' 'systemd-tools' 'iproute2' 'ncurses' 'kbd' 'findutils' 'sysvinit') optdepends=('net-tools: legacy networking support' 'bridge-utils: Network bridging support' -- Sebastien "Seblu" Luttringer
This has been applied already. On Mon, Jun 11, 2012 at 11:10 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/PKGBUILD b/PKGBUILD index 6186de5..0c63e59 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -10,7 +10,7 @@ conflicts=('initscripts') provides=('initscripts=9999') backup=(etc/inittab etc/rc.conf etc/rc.local etc/rc.local.shutdown) makedepends=('asciidoc') -depends=('glibc' 'bash' 'grep' 'coreutils' 'systemd-tools' 'iproute2' +depends=('glibc' 'bash' 'coreutils' 'systemd-tools' 'iproute2' 'ncurses' 'kbd' 'findutils' 'sysvinit') optdepends=('net-tools: legacy networking support' 'bridge-utils: Network bridging support' -- Sebastien "Seblu" Luttringer
ck_depends is no more used and should not be used anymore Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- functions | 9 --------- 1 file changed, 9 deletions(-) diff --git a/functions b/functions index 4a8ba7b..fd52317 100644 --- a/functions +++ b/functions @@ -229,15 +229,6 @@ start_daemon() { have_daemon "$1" && /etc/rc.d/"$1" start } -# Never use this function, it causes daemons to be stoped in the wrong order. -# The only way to start a daemon at boot is to add it to the DAEMONS array. -ck_depends() { - local daemon - for daemon; do - ck_daemon "$daemon" && start_daemon "$daemon" - done -} - start_daemon_bkgd() { stat_bkgd "Starting $1" (start_daemon "$1") >/dev/null & -- Sebastien "Seblu" Luttringer
Looks good. Could you put this (and whatever else gets ack's) in a public branch so it is easy to pull? On Mon, Jun 11, 2012 at 11:10 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
ck_depends is no more used and should not be used anymore
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- functions | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/functions b/functions index 4a8ba7b..fd52317 100644 --- a/functions +++ b/functions @@ -229,15 +229,6 @@ start_daemon() { have_daemon "$1" && /etc/rc.d/"$1" start }
-# Never use this function, it causes daemons to be stoped in the wrong order. -# The only way to start a daemon at boot is to add it to the DAEMONS array. -ck_depends() { - local daemon - for daemon; do - ck_daemon "$daemon" && start_daemon "$daemon" - done -} - start_daemon_bkgd() { stat_bkgd "Starting $1" (start_daemon "$1") >/dev/null & -- Sebastien "Seblu" Luttringer
On Tue, Jun 12, 2012 at 12:15 PM, Tom Gundersen <teg@jklm.no> wrote:
Looks good. Could you put this (and whatever else gets ack's) in a public branch so it is easy to pull? Yes tom, as previous one, you can find it on github : https://github.com/seblu/arch-initscripts
Cheers, -- Sébastien "Seblu" Luttringer www.seblu.net
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.shutdown | 6 +++--- rc.sysinit | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rc.shutdown b/rc.shutdown index c708b92..faa250c 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -27,7 +27,7 @@ status 'Saving Random Seed' /usr/lib/systemd/systemd-random-seed save halt -w # stop monitoring of lvm2 groups before unmounting filesystems -[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) ]] && +[[ ${USELVM,,} == yes && -x $(type -P lvm) ]] && status "Deactivating monitoring of LVM2 groups" vgchange --monitor n # any future uevents can and should be ignored @@ -58,7 +58,7 @@ if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then stat_busy "Deactivating encrypted volumes:" # Maybe someone has LVM on an encrypted block device # executing an extra vgchange is errorless - [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null + [[ ${USELVM,,} == yes ]] && vgchange --sysinit -a n &>/dev/null do_lock() { stat_append "${1}.." if cryptsetup remove "$1" &>/dev/null; then @@ -71,7 +71,7 @@ if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then stat_done fi -[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) ]] && +[[ ${USELVM,,} = yes && -x $(type -P lvm) ]] && status "Deactivating LVM2 groups" vgchange --sysinit -a n &>/dev/null run_hook shutdown_poweroff diff --git a/rc.sysinit b/rc.sysinit index c276da7..12339b6 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -86,11 +86,11 @@ status 'Configuring Virtual Consoles' /usr/lib/systemd/systemd-vconsole-setup status "Bringing up loopback interface" ip link set up dev lo # FakeRAID devices detection -[[ $USEDMRAID = [Yy][Ee][Ss] && -x $(type -P dmraid) ]] && +[[ ${USEDMRAID,,} == yes && -x $(type -P dmraid) ]] && status "Activating FakeRAID arrays" dmraid -i -ay # BTRFS devices detection -[[ $USEBTRFS = [Yy][Ee][Ss] && -x $(type -P btrfs) ]] && +[[ ${USEBTRFS,,} == yes && -x $(type -P btrfs) ]] && status "Activating BTRFS volumes" btrfs device scan # Activate LVM2 groups if any @@ -130,7 +130,7 @@ status "Mounting Local Filesystems" \ run_hook sysinit_postmount # enable monitoring of lvm2 groups, now that the filesystems are mounted rw -[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && +[[ ${USELVM,,} == yes && -x $(type -P lvm) && -d /sys/block ]] && status "Activating monitoring of LVM2 groups" \ vgchange --monitor y >/dev/null -- Sebastien "Seblu" Luttringer
On 12 June 2012 05:10, Sébastien Luttringer <seblu@seblu.net> wrote:
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.shutdown | 6 +++--- rc.sysinit | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) […]
It's worse that mine https://bitbucket.org/poige/arch-initscripts/changeset/1c05cbfa92cf not just due to it's neither mentioning this my efforts commited nor using lowercase "yes" instead of uppercase, but mostly and mainly due to it's bad programming practice/style. Special function, specially named to be be clear and readable in plain is way better. In addition you can easily transform this to /bin/sh or change the way it compares, just because it's more flexible — you wouldn't have to replace all occurrences, just one — inside isYes(). It's not OOP, it's just old as IT subroutines. -- End of message. Next message?
On Tue, Jun 12, 2012 at 05:01:41PM +0800, Igor M Podlesny wrote:
On 12 June 2012 05:10, Sébastien Luttringer <seblu@seblu.net> wrote:
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.shutdown | 6 +++--- rc.sysinit | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) […]
It's worse that mine https://bitbucket.org/poige/arch-initscripts/changeset/1c05cbfa92cf not just due to it's neither mentioning this my efforts commited nor using lowercase "yes" instead of uppercase, but mostly and mainly due to it's bad programming practice/style. Special function, specially named to be be clear and readable in plain is way better. In addition you can easily transform this to /bin/sh or change the way it compares, just because it's more flexible — you wouldn't have to replace all occurrences, just one — inside isYes(). It's not OOP, it's just old as IT subroutines.
-- End of message. Next message?
When you figure out how to use git-send-email, I might consider valuing your opinion about such trivial matters. You might also consider that your patch: 1) doesn't apply to master 2) adds dead code 3) uses camelCase where we use lower_case everywhere else 4) fails to quote properly It's not "IT subroutines", it's about showing some respect for other people in the community of which you're rather new to. Please go away.
On 12 June 2012 18:16, Dave Reisner <d@falconindy.com> wrote:
On Tue, Jun 12, 2012 at 05:01:41PM +0800, Igor M Podlesny wrote: 1) doesn't apply to master
What a tragedy. Are you git newcomer, aren't you?
2) adds dead code
"Dead code" doesn't bite, don't be afraid, boy.
3) uses camelCase where we use lower_case everywhere else
Yeah, I remember yours strict consistency comparing either "yYeEsS" or "YyEeSs" ;-P
4) fails to quote properly
Another tragedy. Feel free to submit patches, dude.
It's not "IT subroutines", it's about showing some respect for other people in the community of which you're rather new to.
Show me your code which doesn't suck, then ask my respect.
Please go away.
Don't play with my toys, you've forgotten to mention. (reminder) -- End of message. Next message?
On 12 June 2012 05:10, Sébastien Luttringer <seblu@seblu.net> wrote:
Signed-off-by: Sébastien Luttringer <seblu@seblu.net>
BTW, one remark in addition — it's not yes/no check. It's just "yes"-check. It matters. -- End of message. Next message?
I don't really see the benefit of this change, so I'm inclined to leave it out. On Mon, Jun 11, 2012 at 11:10 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.shutdown | 6 +++--- rc.sysinit | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/rc.shutdown b/rc.shutdown index c708b92..faa250c 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -27,7 +27,7 @@ status 'Saving Random Seed' /usr/lib/systemd/systemd-random-seed save halt -w
# stop monitoring of lvm2 groups before unmounting filesystems -[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) ]] && +[[ ${USELVM,,} == yes && -x $(type -P lvm) ]] && status "Deactivating monitoring of LVM2 groups" vgchange --monitor n
# any future uevents can and should be ignored @@ -58,7 +58,7 @@ if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then stat_busy "Deactivating encrypted volumes:" # Maybe someone has LVM on an encrypted block device # executing an extra vgchange is errorless - [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null + [[ ${USELVM,,} == yes ]] && vgchange --sysinit -a n &>/dev/null do_lock() { stat_append "${1}.." if cryptsetup remove "$1" &>/dev/null; then @@ -71,7 +71,7 @@ if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then stat_done fi
-[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) ]] && +[[ ${USELVM,,} = yes && -x $(type -P lvm) ]] && status "Deactivating LVM2 groups" vgchange --sysinit -a n &>/dev/null
run_hook shutdown_poweroff diff --git a/rc.sysinit b/rc.sysinit index c276da7..12339b6 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -86,11 +86,11 @@ status 'Configuring Virtual Consoles' /usr/lib/systemd/systemd-vconsole-setup status "Bringing up loopback interface" ip link set up dev lo
# FakeRAID devices detection -[[ $USEDMRAID = [Yy][Ee][Ss] && -x $(type -P dmraid) ]] && +[[ ${USEDMRAID,,} == yes && -x $(type -P dmraid) ]] && status "Activating FakeRAID arrays" dmraid -i -ay
# BTRFS devices detection -[[ $USEBTRFS = [Yy][Ee][Ss] && -x $(type -P btrfs) ]] && +[[ ${USEBTRFS,,} == yes && -x $(type -P btrfs) ]] && status "Activating BTRFS volumes" btrfs device scan
# Activate LVM2 groups if any @@ -130,7 +130,7 @@ status "Mounting Local Filesystems" \ run_hook sysinit_postmount
# enable monitoring of lvm2 groups, now that the filesystems are mounted rw -[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && +[[ ${USELVM,,} == yes && -x $(type -P lvm) && -d /sys/block ]] && status "Activating monitoring of LVM2 groups" \ vgchange --monitor y >/dev/null
-- Sebastien "Seblu" Luttringer
On 12 June 2012 18:16, Tom Gundersen <teg@jklm.no> wrote:
I don't really see the benefit of this change, so I'm inclined to leave it out.
Too bad for you. See http://en.wikipedia.org/wiki/Subroutine -- End of message. Next message?
On Tue, Jun 12, 2012 at 12:16 PM, Tom Gundersen <teg@jklm.no> wrote:
I don't really see the benefit of this change, so I'm inclined to leave it out.
I agree benefits are slight but: - it's nicer to read (and write) - this give a generic way of handling string comparaison from config options. This cannot be an option with long strings like. $toto == [Aa][Ll][Pp][Hh][Aa][Bb][Ee][Tt] ${toto,,} == alphabet Cheers, -- Sébastien "Seblu" Luttringer www.seblu.net
rc.d must have explicit daemon name with command other than list Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.d | 1 - rc.d.8.txt | 6 ------ 2 files changed, 7 deletions(-) diff --git a/rc.d b/rc.d index 0cfbdaf..77852d7 100755 --- a/rc.d +++ b/rc.d @@ -23,7 +23,6 @@ e.g: $name list $name list sshd gpm $name list --started gpm $name start sshd gpm - $name stop --noauto $name help EOF exit ${1:-1} diff --git a/rc.d.8.txt b/rc.d.8.txt index d0bbcce..0f35884 100644 --- a/rc.d.8.txt +++ b/rc.d.8.txt @@ -72,15 +72,9 @@ Examples[[E]] *rc.d start sshd gpm*:: Starts *sshd* and *gpm* scripts. -*rc.d start --auto --stopped*:: - Starts all stopped scripts which are started at startup. - *rc.d stop crond*:: Stops the *crond* script. -*rc.d stop --noauto*:: - Stop all script which are not runned at startup - *rc.d restart crond*:: Restarts the *crond* script. -- Sebastien "Seblu" Luttringer
Looks good. On Mon, Jun 11, 2012 at 11:10 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
rc.d must have explicit daemon name with command other than list
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.d | 1 - rc.d.8.txt | 6 ------ 2 files changed, 7 deletions(-)
diff --git a/rc.d b/rc.d index 0cfbdaf..77852d7 100755 --- a/rc.d +++ b/rc.d @@ -23,7 +23,6 @@ e.g: $name list $name list sshd gpm $name list --started gpm $name start sshd gpm - $name stop --noauto $name help EOF exit ${1:-1} diff --git a/rc.d.8.txt b/rc.d.8.txt index d0bbcce..0f35884 100644 --- a/rc.d.8.txt +++ b/rc.d.8.txt @@ -72,15 +72,9 @@ Examples[[E]] *rc.d start sshd gpm*:: Starts *sshd* and *gpm* scripts.
-*rc.d start --auto --stopped*:: - Starts all stopped scripts which are started at startup. - *rc.d stop crond*:: Stops the *crond* script.
-*rc.d stop --noauto*:: - Stop all script which are not runned at startup - *rc.d restart crond*:: Restarts the *crond* script.
-- Sebastien "Seblu" Luttringer
This patch use Linux kernel cgroups to manage daemons. No controler is used. Cgroups are only used to track launched process and prevent escape. Notable changes: ---------------- - /run/daemons have switched to /sys/fs/cgroups/initscripts/daemons We now embded running dameon information into cgroup filesystem directly. No need to maintain both hierarchies. - DAEMONS array in rc.conf understand a new modifier: - Some daemons can be launched out of its cgroup container. This will avoid stopping it remove all its children (e.g: sshd) - rc scripts must be launched with rc.d tool. Launching daemon directly from /etc/rc.d/x inherits current environment and it may differ from environment at startup and leads to errors. Here is one stone hits two. We clean environment and we use this to auto cgroup launched daemons without need to update each rc script. - hooks calling directly rc scripts will fail (e.g: sshd). They must be fixed to use proper initscripts functions (run_daemon ssh stop). - rc.d tools now handle same syntax as DAEMONS array. By example, rc.d start @sshd or rc.d start -- -sshd This patch should be fully backward compatible with existant rc.d scripts but not with hooks. --- Makefile | 2 - bash-completion | 4 +- functions | 123 +++++++++++++++++++++++++++++++++++++++++++------------ rc.conf.5.txt | 1 + rc.d | 49 +++++++++++----------- rc.d.8.txt | 6 +++ rc.multi | 6 +-- rc.single | 2 +- rc.sysinit | 7 +++- tmpfiles.conf | 5 --- zsh-completion | 4 +- 11 files changed, 139 insertions(+), 70 deletions(-) delete mode 100644 tmpfiles.conf diff --git a/Makefile b/Makefile index 825eb11..cbde5b2 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ DIRS := \ /etc/rc.d/functions.d \ /etc/logrotate.d \ /etc/profile.d \ - /usr/lib/tmpfiles.d \ /usr/sbin \ /usr/share/bash-completion/completions \ /usr/share/zsh/site-functions \ @@ -28,7 +27,6 @@ install: installdirs doc install -m755 -t $(DESTDIR)/usr/sbin rc.d install -m644 -t $(DESTDIR)/usr/share/man/man5 rc.conf.5 install -m644 -t $(DESTDIR)/usr/share/man/man8 rc.d.8 - install -m644 tmpfiles.conf $(DESTDIR)/usr/lib/tmpfiles.d/initscripts.conf install -m644 -T bash-completion $(DESTDIR)/usr/share/bash-completion/completions/rc.d install -m644 -T zsh-completion $(DESTDIR)/usr/share/zsh/site-functions/_rc.d diff --git a/bash-completion b/bash-completion index 4b4593b..dd8b006 100644 --- a/bash-completion +++ b/bash-completion @@ -12,9 +12,9 @@ _rc_d() elif [[ "$arg" == help ]]; then COMPREPLY=() elif [[ "$arg" == start ]]; then - COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /run/daemons/ && compgen -f "$cur"|sort))) + COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /sys/fs/cgroup/initscripts/daemons/ && compgen -d "$cur"|sort))) elif [[ "$arg" =~ stop|restart|reload ]]; then - COMPREPLY=($(cd /run/daemons/ && compgen -f "$cur"|sort)) + COMPREPLY=($(cd /sys/fs/cgroup/initscripts/daemons/ && compgen -d "$cur"|sort)) else COMPREPLY=($(compgen -W "${options} $(cd /etc/rc.d && compgen -f -X 'functions*')" -- "$cur")) fi diff --git a/functions b/functions index fd52317..0669810 100644 --- a/functions +++ b/functions @@ -11,14 +11,6 @@ localevars=(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY vconsolevars=(KEYMAP KEYMAP_TOGGLE FONT FONT_MAP FONT_UNIMAP) -if [[ $1 == "start" ]]; then - if [[ $STARTING ]]; then - echo "A daemon is starting another daemon, this is unlikely to work as intended." - else - export STARTING=1 - fi -fi - # width: calc_columns () { STAT_COL=80 @@ -198,44 +190,116 @@ in_array() { # daemons: +# Deprecated function used by daemon scripts to tell a daemon is running add_daemon() { - [[ -d /run/daemons ]] || mkdir -p /run/daemons - >| /run/daemons/"$1" + true } +# Deprecated function used by daemon scripts to tell a daemon is no more running rm_daemon() { - rm -f /run/daemons/"$1" + true +} + +# Return array with daemon name and prefix in fixed order +# $1 daemon name with prefix +# return ('daemon' '@' '-' '!') +strip_daemon() { + local name=$1 + while (( ${#name} > 0 )); do + case ${name:0:1} in + '!'|'@'|'-') name=${name:1};; + *) break;; + esac + done + echo $name } +# Return 1 if daemon $1 is running, else 0 +# Daemons started without running process return 1 +# Keep check on /run/daemons/$1 (useful until first user reboot) ck_daemon() { - [[ ! -f /run/daemons/$1 ]] + [[ ! -d /sys/fs/cgroup/initscripts/daemons/$1 && ! -f /run/daemons/$1 ]] } -# Check if $1 is a valid daemon name +# Return 0 if $1 is a valid daemon name have_daemon() { [[ -f /etc/rc.d/$1 && -x /etc/rc.d/$1 ]] } # Check if $1 is started at boot +# Return 1 if autostarted, otherwise 0 ck_autostart() { local daemon for daemon in "${DAEMONS[@]}"; do - [[ $1 = "${daemon#@}" ]] && return 1 + [[ $daemon =~ ^[@-]*${1}$ ]] && return 1 done return 0 } -start_daemon() { - have_daemon "$1" && /etc/rc.d/"$1" start +# Run action $2 for daemon $1 +# This function understand prefixes: ! @ - +run_daemon() { + local background=0 + local cgroup=1 + local name=$1 + while (( ${#name} > 0 )); do + case ${name:0:1} in + '!') return 1;; + '@') background=1;; + '-') cgroup=0;; + *) break;; + esac + name=${name:1} + done + have_daemon "$name" || return 1 + # start action register daemon + if [[ $2 == start ]]; then + if [[ -d /sys/fs/cgroup/initscripts/daemons ]]; then + mkdir -p -m755 /sys/fs/cgroup/initscripts/daemons/"$name" + elif [[ -d /run/daemons ]]; then + >| /run/daemons/"$name" + fi + fi + # daemon script stuff + ( + # use cgroup jail + (( $cgroup )) && [[ -w "/sys/fs/cgroup/initscripts/daemons/$name/tasks" ]] && + echo $BASHPID > "/sys/fs/cgroup/initscripts/daemons/$name/tasks" + # execute script + if (( $background )); then + stat_bkgd "${2^} $name" + exec_daemon /etc/rc.d/"$name" "$2" >/dev/null & + else + exec_daemon /etc/rc.d/"$name" "$2" + fi + ) + # stop action unregister and cleanup + if [[ $2 == stop ]]; then + kill_daemon "$1" + rmdir "/sys/fs/cgroup/initscripts/daemons/$1" 2>/dev/null + # remove legacy file (useful until first user reboot) + rm -f "/run/daemons/$1" 2>/dev/null + fi } -start_daemon_bkgd() { - stat_bkgd "Starting $1" - (start_daemon "$1") >/dev/null & +# Execute a daemon script code properly +# This means with a clean environment and under the root directory +exec_daemon() { + ENV=('PATH=/bin:/usr/bin:/sbin:/usr/sbin' + 'CONSOLE=/dev/console' + 'TERM=linux' + 'INITSCRIPTS_LAUNCHER=1') + cd / + exec env -i "${ENV[@]}" bash -l "$@" } -stop_daemon() { - have_daemon "$1" && /etc/rc.d/"$1" stop +# use cgroup to kill all process runned by dameon $1 +kill_daemon() { + [[ -r /sys/fs/cgroup/initscripts/daemons/$1/tasks ]] || return + d=$(< "/sys/fs/cgroup/initscripts/daemons/$1/tasks") + [[ -n $d ]] && { kill -15 $d &>/dev/null; sleep .25; } || return + d=$(< "/sys/fs/cgroup/initscripts/daemons/$1/tasks") + [[ -n $d ]] && kill -9 $d &>/dev/null } # Status functions @@ -277,15 +341,15 @@ add_omit_pids() { } # Stop all daemons -# This function should *never* ever perform any other actions beside calling stop_daemon()! +# This function should *never* ever perform any other actions beside stoping daemons # It might be used by a splash system etc. to get a list of daemons to be stopped. stop_all_daemons() { # Find daemons NOT in the DAEMONS array. Shut these down first local daemon - for daemon in /run/daemons/*; do - [[ -f $daemon ]] || continue + for daemon in /sys/fs/cgroup/initscripts/daemons/*; do + [[ -d $daemon ]] || continue daemon=${daemon##*/} - ck_autostart "$daemon" && stop_daemon "$daemon" + ck_autostart "$daemon" && run_daemon "$daemon" stop done # Shutdown daemons in reverse order @@ -293,7 +357,7 @@ stop_all_daemons() { for (( i=${#DAEMONS[@]}-1; i>=0; i-- )); do [[ ${DAEMONS[i]} = '!'* ]] && continue daemon=${DAEMONS[i]#@} - ck_daemon "$daemon" || stop_daemon "$daemon" + ck_daemon "$daemon" || run_daemon "$daemon" stop done } @@ -696,5 +760,12 @@ for f in /etc/rc.d/functions.d/*; do [[ -e $f ]] && . "$f" done +# initscripts must not be called directly +if [[ $0 =~ /etc/rc.d/* && -z $INITSCRIPTS_LAUNCHER ]]; then + printf "${C_FAIL}You have to run your initscript with rc.d tools${C_CLEAR}\n" >&2 + printf "e.g: ${C_MAIN}rc.d ${1:-start} ${0##*/}${C_CLEAR}\n" >&2 + exit 42 +fi + # End of file # vim: set ts=2 sw=2 noet: diff --git a/rc.conf.5.txt b/rc.conf.5.txt index 726ba23..a102f4c 100644 --- a/rc.conf.5.txt +++ b/rc.conf.5.txt @@ -210,6 +210,7 @@ DAEMONS[[D]] Daemons to start at boot-up (in this order) - prefix a daemon with a ! to disable it - prefix a daemon with a @ to start it up in the background + - prefix a daemon with a - to start it outside a cgroup If you are sure nothing else touches your hardware clock (such as ntpd or a dual-boot), you might want to enable 'hwclock'. Note that this will only diff --git a/rc.d b/rc.d index 77852d7..fad1e18 100755 --- a/rc.d +++ b/rc.d @@ -23,6 +23,8 @@ e.g: $name list $name list sshd gpm $name list --started gpm $name start sshd gpm + $name start -- -sshd + $name start -- @acpid -sshd gpm $name help EOF exit ${1:-1} @@ -30,8 +32,7 @@ EOF # filter list of daemons filter_daemons() { - local -a new_daemons=() - for daemon in "${daemons[@]}"; do + for daemon in "${!daemons[@]}"; do # check if daemons is valid if ! have_daemon "$daemon"; then printf "${C_FAIL}:: ${C_DONE}Daemon script ${C_FAIL}${daemon}${C_DONE} does \ @@ -39,13 +40,11 @@ not exist or is not executable.${C_CLEAR}\n" >&2 exit 2 fi # check filter - (( ${filter[started]} )) && ck_daemon "$daemon" && continue - (( ${filter[stopped]} )) && ! ck_daemon "$daemon" && continue - (( ${filter[auto]} )) && ck_autostart "$daemon" && continue - (( ${filter[noauto]} )) && ! ck_autostart "$daemon" && continue - new_daemons+=("$daemon") + (( ${filter[started]} )) && ck_daemon "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[stopped]} )) && ! ck_daemon "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[auto]} )) && ck_autostart "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[noauto]} )) && ! ck_autostart "$daemon" && unset daemons["$daemon"] && continue done - daemons=("${new_daemons[@]}") } (( $# < 1 )) && usage @@ -53,7 +52,7 @@ not exist or is not executable.${C_CLEAR}\n" >&2 # ret store the return code of rc.d declare -i ret=0 # daemons store daemons on which action will be executed -declare -a daemons=() +declare -A daemons=() # filter store current filter mode declare -A filter=([started]=0 [stopped]=0 [auto]=0 [noauto]=0) @@ -80,7 +79,7 @@ shift # get initial daemons list for daemon; do - daemons+=("$daemon") + daemons[$(strip_daemon "$daemon")]=$daemon done # going into script directory @@ -91,10 +90,15 @@ case $action in usage 0 2>&1 ;; list) - # list take all daemons by default - [[ -z $daemons ]] && for d in *; do have_daemon "$d" && daemons+=("$d"); done - filter_daemons - for daemon in "${daemons[@]}"; do + # list take all daemons if not specified + if (( ${#daemons[*]} == 0)); then + for d in *; do + have_daemon "$d" && daemons[$(strip_daemon "$d")]=$daemon + done + fi + # use filters if needed + (( ${#filter[*]} > 0 )) && filter_daemons + for daemon in "${!daemons[@]}"; do # print running / stopped satus if ! ck_daemon "$daemon"; then s_status="${C_OTHER}[${C_DONE}STARTED${C_OTHER}]" @@ -112,18 +116,11 @@ case $action in ;; *) # other actions need an explicit daemons list - [[ -z $daemons ]] && usage - filter_daemons - # set same environment variables as init - runlevel=$(/sbin/runlevel) - ENV=('PATH=/bin:/usr/bin:/sbin:/usr/sbin' - "PREVLEVEL=${runlevel%% *}" - "RUNLEVEL=${runlevel##* }" - "CONSOLE=${CONSOLE:-/dev/console}" - "TERM=$TERM") - cd / - for daemon in "${daemons[@]}"; do - env -i "${ENV[@]}" "/etc/rc.d/$daemon" "$action" + (( ${#daemons[*]} == 0 )) && usage + # use filters if needed + (( ${#filter[*]} > 0 )) && filter_daemons + for daemon in "${!daemons[@]}"; do + run_daemon "${daemons[$daemon]}" "$action" (( ret += !! $? )) # clamp exit value to 0/1 done ;; diff --git a/rc.d.8.txt b/rc.d.8.txt index 0f35884..3f7e41f 100644 --- a/rc.d.8.txt +++ b/rc.d.8.txt @@ -72,6 +72,12 @@ Examples[[E]] *rc.d start sshd gpm*:: Starts *sshd* and *gpm* scripts. +*rc.d start -- -sshd*:: + Starts *sshd* without cgroup jaling. + +*rc.d start -- @-sshd @acpid @gpm*:: + Starts *sshd*, *acpid* and *gpm* in background. + *rc.d stop crond*:: Stops the *crond* script. diff --git a/rc.multi b/rc.multi index d558753..d747113 100755 --- a/rc.multi +++ b/rc.multi @@ -16,11 +16,7 @@ run_hook multi_start # Start daemons for daemon in "${DAEMONS[@]}"; do - case ${daemon:0:1} in - '!') continue;; # Skip this daemon. - '@') start_daemon_bkgd "${daemon#@}";; - *) start_daemon "$daemon";; - esac + run_daemon "$daemon" start done [[ -x /etc/rc.local ]] && /etc/rc.local diff --git a/rc.single b/rc.single index aec026c..ec343fe 100755 --- a/rc.single +++ b/rc.single @@ -20,7 +20,7 @@ if [[ $PREVLEVEL != N ]]; then # Start/trigger UDev, load MODULES and settle UDev udevd_modprobe single - + # Removing leftover files remove_leftover fi diff --git a/rc.sysinit b/rc.sysinit index 12339b6..bba57b5 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -12,7 +12,7 @@ printhl "${C_H2}http://www.archlinux.org" printsep # mount the api filesystems -# /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm +# /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm, /sys/fs/cgroup/initscripts mountpoint -q /proc || mount -t proc proc /proc -o nosuid,noexec,nodev mountpoint -q /sys || mount -t sysfs sys /sys -o nosuid,noexec,nodev mountpoint -q /run || mount -t tmpfs run /run -o mode=0755,nosuid,nodev @@ -25,6 +25,11 @@ mountpoint -q /dev/shm || mount /dev/shm &>/dev/null || mount -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev mountpoint -q /proc/sys/fs/binfmt_misc || mount /proc/sys/fs/binfmt_misc &>/dev/null || mount -t binfmt_misc binfmt /proc/sys/fs/binfmt_misc +mountpoint -q /sys/fs/cgroup || + mount -n -t tmpfs cgroup /sys/fs/cgroup -o mode=0755,nosuid,noexec,nodev +mkdir -p /sys/fs/cgroup/initscripts +mount -t cgroup -o none,name=initscripts cgroup /sys/fs/cgroup/initscripts +mkdir -p /sys/fs/cgroup/initscripts/daemons if [[ ! -e /run/initramfs/fsck-root ]]; then # remount root ro to allow for fsck later on, we remount now to diff --git a/tmpfiles.conf b/tmpfiles.conf deleted file mode 100644 index 8f99a99..0000000 --- a/tmpfiles.conf +++ /dev/null @@ -1,5 +0,0 @@ -# -# /usr/lib/tmpfiles.d/arch.conf -# - -d /run/daemons 0755 root root - diff --git a/zsh-completion b/zsh-completion index d860e51..64cbc2a 100644 --- a/zsh-completion +++ b/zsh-completion @@ -18,10 +18,10 @@ _rc.d () { _arguments "*: :" ;; start) - _arguments "*: :($(comm -23 <(echo /etc/rc.d/*(N-*:t)|tr ' ' '\n') <(echo /run/daemons/*(N:t)|tr ' ' '\n')))" + _arguments "*: :($(comm -23 <(echo /etc/rc.d/*(N-*:t)|tr ' ' '\n') <(echo /sys/fs/cgroup/initscripts/daemons/*(N/:t)|tr ' ' '\n')))" ;; stop|restart|reload) - _arguments "*: :(/run/daemons/*(N:t))" + _arguments "*: :(/sys/fs/cgroup/initscripts/daemons/*(N/:t))" ;; *) _arguments "*: :(/etc/rc.d/*(N-*:t))" -- Sebastien "Seblu" Luttringer
On Mon, Jun 11, 2012 at 11:10:40PM +0200, Sébastien Luttringer wrote:
This patch use Linux kernel cgroups to manage daemons. No controler is used. Cgroups are only used to track launched process and prevent escape.
Notable changes: ----------------
- /run/daemons have switched to /sys/fs/cgroups/initscripts/daemons We now embded running dameon information into cgroup filesystem directly. No need to maintain both hierarchies.
- DAEMONS array in rc.conf understand a new modifier: - Some daemons can be launched out of its cgroup container. This will avoid stopping it remove all its children (e.g: sshd)
- rc scripts must be launched with rc.d tool. Launching daemon directly from /etc/rc.d/x inherits current environment and it may differ from environment at startup and leads to errors. Here is one stone hits two. We clean environment and we use this to auto cgroup launched daemons without need to update each rc script.
- hooks calling directly rc scripts will fail (e.g: sshd). They must be fixed to use proper initscripts functions (run_daemon ssh stop).
- rc.d tools now handle same syntax as DAEMONS array. By example, rc.d start @sshd or rc.d start -- -sshd
This patch should be fully backward compatible with existant rc.d scripts but not with hooks.
So what do people who compile their own kernels without cgroups do? Unless I'm missing something, you get a huge NACK from me based on the way you're shutting down processes. Comments inline.
--- Makefile | 2 - bash-completion | 4 +- functions | 123 +++++++++++++++++++++++++++++++++++++++++++------------ rc.conf.5.txt | 1 + rc.d | 49 +++++++++++----------- rc.d.8.txt | 6 +++ rc.multi | 6 +-- rc.single | 2 +- rc.sysinit | 7 +++- tmpfiles.conf | 5 --- zsh-completion | 4 +- 11 files changed, 139 insertions(+), 70 deletions(-) delete mode 100644 tmpfiles.conf
diff --git a/Makefile b/Makefile index 825eb11..cbde5b2 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ DIRS := \ /etc/rc.d/functions.d \ /etc/logrotate.d \ /etc/profile.d \ - /usr/lib/tmpfiles.d \ /usr/sbin \ /usr/share/bash-completion/completions \ /usr/share/zsh/site-functions \ @@ -28,7 +27,6 @@ install: installdirs doc install -m755 -t $(DESTDIR)/usr/sbin rc.d install -m644 -t $(DESTDIR)/usr/share/man/man5 rc.conf.5 install -m644 -t $(DESTDIR)/usr/share/man/man8 rc.d.8 - install -m644 tmpfiles.conf $(DESTDIR)/usr/lib/tmpfiles.d/initscripts.conf install -m644 -T bash-completion $(DESTDIR)/usr/share/bash-completion/completions/rc.d install -m644 -T zsh-completion $(DESTDIR)/usr/share/zsh/site-functions/_rc.d
diff --git a/bash-completion b/bash-completion index 4b4593b..dd8b006 100644 --- a/bash-completion +++ b/bash-completion @@ -12,9 +12,9 @@ _rc_d() elif [[ "$arg" == help ]]; then COMPREPLY=() elif [[ "$arg" == start ]]; then - COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /run/daemons/ && compgen -f "$cur"|sort))) + COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /sys/fs/cgroup/initscripts/daemons/ && compgen -d "$cur"|sort))) elif [[ "$arg" =~ stop|restart|reload ]]; then - COMPREPLY=($(cd /run/daemons/ && compgen -f "$cur"|sort)) + COMPREPLY=($(cd /sys/fs/cgroup/initscripts/daemons/ && compgen -d "$cur"|sort)) else COMPREPLY=($(compgen -W "${options} $(cd /etc/rc.d && compgen -f -X 'functions*')" -- "$cur")) fi diff --git a/functions b/functions index fd52317..0669810 100644 --- a/functions +++ b/functions @@ -11,14 +11,6 @@ localevars=(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY
vconsolevars=(KEYMAP KEYMAP_TOGGLE FONT FONT_MAP FONT_UNIMAP)
-if [[ $1 == "start" ]]; then - if [[ $STARTING ]]; then - echo "A daemon is starting another daemon, this is unlikely to work as intended." - else - export STARTING=1 - fi -fi - # width: calc_columns () { STAT_COL=80 @@ -198,44 +190,116 @@ in_array() {
# daemons:
+# Deprecated function used by daemon scripts to tell a daemon is running
"to tell if a daemon is running"
add_daemon() { - [[ -d /run/daemons ]] || mkdir -p /run/daemons - >| /run/daemons/"$1" + true }
+# Deprecated function used by daemon scripts to tell a daemon is no more running
"to tell if a daemon is not running"
rm_daemon() { - rm -f /run/daemons/"$1" + true +} + +# Return array with daemon name and prefix in fixed order +# $1 daemon name with prefix +# return ('daemon' '@' '-' '!') +strip_daemon() { + local name=$1 + while (( ${#name} > 0 )); do + case ${name:0:1} in + '!'|'@'|'-') name=${name:1};;
No need for a while loop here just to trim a string... name=${name##+(!|@|-)}
+ *) break;; + esac + done + echo $name
Quote, please.
}
+# Return 1 if daemon $1 is running, else 0 +# Daemons started without running process return 1 +# Keep check on /run/daemons/$1 (useful until first user reboot) ck_daemon() { - [[ ! -f /run/daemons/$1 ]] + [[ ! -d /sys/fs/cgroup/initscripts/daemons/$1 && ! -f /run/daemons/$1 ]] }
-# Check if $1 is a valid daemon name +# Return 0 if $1 is a valid daemon name have_daemon() { [[ -f /etc/rc.d/$1 && -x /etc/rc.d/$1 ]] }
# Check if $1 is started at boot +# Return 1 if autostarted, otherwise 0 ck_autostart() { local daemon for daemon in "${DAEMONS[@]}"; do - [[ $1 = "${daemon#@}" ]] && return 1 + [[ $daemon =~ ^[@-]*${1}$ ]] && return 1
No need for a regex. [[ $daemon = *([@-])$1 ]] && return 1
done return 0 }
-start_daemon() { - have_daemon "$1" && /etc/rc.d/"$1" start +# Run action $2 for daemon $1 +# This function understand prefixes: ! @ -
understands
+run_daemon() { + local background=0 + local cgroup=1 + local name=$1 + while (( ${#name} > 0 )); do + case ${name:0:1} in + '!') return 1;; + '@') background=1;; + '-') cgroup=0;; + *) break;; + esac + name=${name:1} + done + have_daemon "$name" || return 1 + # start action register daemon + if [[ $2 == start ]]; then + if [[ -d /sys/fs/cgroup/initscripts/daemons ]]; then + mkdir -p -m755 /sys/fs/cgroup/initscripts/daemons/"$name" + elif [[ -d /run/daemons ]]; then + >| /run/daemons/"$name" + fi + fi + # daemon script stuff + ( + # use cgroup jail + (( $cgroup )) && [[ -w "/sys/fs/cgroup/initscripts/daemons/$name/tasks" ]] &&
Don't force this expansion (( cgroup )) is fine. The quoting isn't needed either.
+ echo $BASHPID > "/sys/fs/cgroup/initscripts/daemons/$name/tasks" + # execute script + if (( $background )); then
Same here.
+ stat_bkgd "${2^} $name"
This is the only place you sentence case a daemon name in the output. Intentional?
+ exec_daemon /etc/rc.d/"$name" "$2" >/dev/null & + else + exec_daemon /etc/rc.d/"$name" "$2" + fi + ) + # stop action unregister and cleanup + if [[ $2 == stop ]]; then + kill_daemon "$1"
So that's it? We just call kill daemon here and don't even honor the script's own stop function anymore?
+ rmdir "/sys/fs/cgroup/initscripts/daemons/$1" 2>/dev/null + # remove legacy file (useful until first user reboot) + rm -f "/run/daemons/$1" 2>/dev/null + fi }
-start_daemon_bkgd() { - stat_bkgd "Starting $1" - (start_daemon "$1") >/dev/null & +# Execute a daemon script code properly
'script code' is rather redundant. "Execute a script with a clean environment"
+# This means with a clean environment and under the root directory +exec_daemon() { + ENV=('PATH=/bin:/usr/bin:/sbin:/usr/sbin' + 'CONSOLE=/dev/console' + 'TERM=linux' + 'INITSCRIPTS_LAUNCHER=1') + cd / + exec env -i "${ENV[@]}" bash -l "$@" }
-stop_daemon() { - have_daemon "$1" && /etc/rc.d/"$1" stop +# use cgroup to kill all process runned by dameon $1
"run by daemon"
+kill_daemon() { + [[ -r /sys/fs/cgroup/initscripts/daemons/$1/tasks ]] || return + d=$(< "/sys/fs/cgroup/initscripts/daemons/$1/tasks") + [[ -n $d ]] && { kill -15 $d &>/dev/null; sleep .25; } || return
OCD: Is it really too much to ask to write this as a proper if/then? After only 1/4 of a second you send the death touch onto all tasks? Go take a look at a service like squid or mysql that can survive at _least_ 5-10s after receiving a TERM. What about services that don't respond to a TERM, but would exit on a HUP? They're going to be invariably death touched. This is way too simple of a heuristic to be healthy.
+ d=$(< "/sys/fs/cgroup/initscripts/daemons/$1/tasks") + [[ -n $d ]] && kill -9 $d &>/dev/null }
# Status functions @@ -277,15 +341,15 @@ add_omit_pids() { }
# Stop all daemons -# This function should *never* ever perform any other actions beside calling stop_daemon()! +# This function should *never* ever perform any other actions beside stoping daemons
stopping
# It might be used by a splash system etc. to get a list of daemons to be stopped. stop_all_daemons() { # Find daemons NOT in the DAEMONS array. Shut these down first local daemon - for daemon in /run/daemons/*; do - [[ -f $daemon ]] || continue + for daemon in /sys/fs/cgroup/initscripts/daemons/*; do + [[ -d $daemon ]] || continue daemon=${daemon##*/} - ck_autostart "$daemon" && stop_daemon "$daemon" + ck_autostart "$daemon" && run_daemon "$daemon" stop done
# Shutdown daemons in reverse order @@ -293,7 +357,7 @@ stop_all_daemons() { for (( i=${#DAEMONS[@]}-1; i>=0; i-- )); do [[ ${DAEMONS[i]} = '!'* ]] && continue daemon=${DAEMONS[i]#@} - ck_daemon "$daemon" || stop_daemon "$daemon" + ck_daemon "$daemon" || run_daemon "$daemon" stop done }
@@ -696,5 +760,12 @@ for f in /etc/rc.d/functions.d/*; do [[ -e $f ]] && . "$f" done
+# initscripts must not be called directly +if [[ $0 =~ /etc/rc.d/* && -z $INITSCRIPTS_LAUNCHER ]]; then
This doesn't match what you want, nor is $0 a reliable way to check the path of a script. The regex as you have it will match "/etc/rcdd". You really just wanted a glob here.
+ printf "${C_FAIL}You have to run your initscript with rc.d tools${C_CLEAR}\n" >&2
"Daemons must be controlled via rc.d"
+ printf "e.g: ${C_MAIN}rc.d ${1:-start} ${0##*/}${C_CLEAR}\n" >&2
Magic help messages which change text? Can't we just generalize it?
+ exit 42 +fi + # End of file # vim: set ts=2 sw=2 noet: diff --git a/rc.conf.5.txt b/rc.conf.5.txt index 726ba23..a102f4c 100644 --- a/rc.conf.5.txt +++ b/rc.conf.5.txt @@ -210,6 +210,7 @@ DAEMONS[[D]] Daemons to start at boot-up (in this order) - prefix a daemon with a ! to disable it - prefix a daemon with a @ to start it up in the background + - prefix a daemon with a - to start it outside a cgroup
If you are sure nothing else touches your hardware clock (such as ntpd or a dual-boot), you might want to enable 'hwclock'. Note that this will only diff --git a/rc.d b/rc.d index 77852d7..fad1e18 100755 --- a/rc.d +++ b/rc.d @@ -23,6 +23,8 @@ e.g: $name list $name list sshd gpm $name list --started gpm $name start sshd gpm + $name start -- -sshd + $name start -- @acpid -sshd gpm $name help EOF exit ${1:-1} @@ -30,8 +32,7 @@ EOF
# filter list of daemons filter_daemons() { - local -a new_daemons=() - for daemon in "${daemons[@]}"; do + for daemon in "${!daemons[@]}"; do # check if daemons is valid if ! have_daemon "$daemon"; then printf "${C_FAIL}:: ${C_DONE}Daemon script ${C_FAIL}${daemon}${C_DONE} does \ @@ -39,13 +40,11 @@ not exist or is not executable.${C_CLEAR}\n" >&2 exit 2 fi # check filter - (( ${filter[started]} )) && ck_daemon "$daemon" && continue - (( ${filter[stopped]} )) && ! ck_daemon "$daemon" && continue - (( ${filter[auto]} )) && ck_autostart "$daemon" && continue - (( ${filter[noauto]} )) && ! ck_autostart "$daemon" && continue - new_daemons+=("$daemon") + (( ${filter[started]} )) && ck_daemon "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[stopped]} )) && ! ck_daemon "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[auto]} )) && ck_autostart "$daemon" && unset daemons["$daemon"] && continue + (( ${filter[noauto]} )) && ! ck_autostart "$daemon" && unset daemons["$daemon"] && continue done - daemons=("${new_daemons[@]}") }
(( $# < 1 )) && usage @@ -53,7 +52,7 @@ not exist or is not executable.${C_CLEAR}\n" >&2 # ret store the return code of rc.d declare -i ret=0 # daemons store daemons on which action will be executed -declare -a daemons=() +declare -A daemons=() # filter store current filter mode declare -A filter=([started]=0 [stopped]=0 [auto]=0 [noauto]=0)
@@ -80,7 +79,7 @@ shift
# get initial daemons list for daemon; do - daemons+=("$daemon") + daemons[$(strip_daemon "$daemon")]=$daemon done
# going into script directory @@ -91,10 +90,15 @@ case $action in usage 0 2>&1 ;; list) - # list take all daemons by default - [[ -z $daemons ]] && for d in *; do have_daemon "$d" && daemons+=("$d"); done - filter_daemons - for daemon in "${daemons[@]}"; do + # list take all daemons if not specified + if (( ${#daemons[*]} == 0)); then + for d in *; do + have_daemon "$d" && daemons[$(strip_daemon "$d")]=$daemon + done + fi + # use filters if needed + (( ${#filter[*]} > 0 )) && filter_daemons + for daemon in "${!daemons[@]}"; do # print running / stopped satus if ! ck_daemon "$daemon"; then s_status="${C_OTHER}[${C_DONE}STARTED${C_OTHER}]" @@ -112,18 +116,11 @@ case $action in ;; *) # other actions need an explicit daemons list - [[ -z $daemons ]] && usage - filter_daemons - # set same environment variables as init - runlevel=$(/sbin/runlevel) - ENV=('PATH=/bin:/usr/bin:/sbin:/usr/sbin' - "PREVLEVEL=${runlevel%% *}" - "RUNLEVEL=${runlevel##* }" - "CONSOLE=${CONSOLE:-/dev/console}" - "TERM=$TERM") - cd / - for daemon in "${daemons[@]}"; do - env -i "${ENV[@]}" "/etc/rc.d/$daemon" "$action" + (( ${#daemons[*]} == 0 )) && usage + # use filters if needed + (( ${#filter[*]} > 0 )) && filter_daemons + for daemon in "${!daemons[@]}"; do + run_daemon "${daemons[$daemon]}" "$action" (( ret += !! $? )) # clamp exit value to 0/1 done ;; diff --git a/rc.d.8.txt b/rc.d.8.txt index 0f35884..3f7e41f 100644 --- a/rc.d.8.txt +++ b/rc.d.8.txt @@ -72,6 +72,12 @@ Examples[[E]] *rc.d start sshd gpm*:: Starts *sshd* and *gpm* scripts.
+*rc.d start -- -sshd*:: + Starts *sshd* without cgroup jaling. + +*rc.d start -- @-sshd @acpid @gpm*:: + Starts *sshd*, *acpid* and *gpm* in background. + *rc.d stop crond*:: Stops the *crond* script.
diff --git a/rc.multi b/rc.multi index d558753..d747113 100755 --- a/rc.multi +++ b/rc.multi @@ -16,11 +16,7 @@ run_hook multi_start
# Start daemons for daemon in "${DAEMONS[@]}"; do - case ${daemon:0:1} in - '!') continue;; # Skip this daemon. - '@') start_daemon_bkgd "${daemon#@}";; - *) start_daemon "$daemon";; - esac + run_daemon "$daemon" start done
[[ -x /etc/rc.local ]] && /etc/rc.local diff --git a/rc.single b/rc.single index aec026c..ec343fe 100755 --- a/rc.single +++ b/rc.single @@ -20,7 +20,7 @@ if [[ $PREVLEVEL != N ]]; then
# Start/trigger UDev, load MODULES and settle UDev udevd_modprobe single - + # Removing leftover files remove_leftover fi diff --git a/rc.sysinit b/rc.sysinit index 12339b6..bba57b5 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -12,7 +12,7 @@ printhl "${C_H2}http://www.archlinux.org" printsep
# mount the api filesystems -# /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm +# /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm, /sys/fs/cgroup/initscripts mountpoint -q /proc || mount -t proc proc /proc -o nosuid,noexec,nodev mountpoint -q /sys || mount -t sysfs sys /sys -o nosuid,noexec,nodev mountpoint -q /run || mount -t tmpfs run /run -o mode=0755,nosuid,nodev @@ -25,6 +25,11 @@ mountpoint -q /dev/shm || mount /dev/shm &>/dev/null || mount -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev mountpoint -q /proc/sys/fs/binfmt_misc || mount /proc/sys/fs/binfmt_misc &>/dev/null || mount -t binfmt_misc binfmt /proc/sys/fs/binfmt_misc +mountpoint -q /sys/fs/cgroup || + mount -n -t tmpfs cgroup /sys/fs/cgroup -o mode=0755,nosuid,noexec,nodev +mkdir -p /sys/fs/cgroup/initscripts +mount -t cgroup -o none,name=initscripts cgroup /sys/fs/cgroup/initscripts +mkdir -p /sys/fs/cgroup/initscripts/daemons
if [[ ! -e /run/initramfs/fsck-root ]]; then # remount root ro to allow for fsck later on, we remount now to diff --git a/tmpfiles.conf b/tmpfiles.conf deleted file mode 100644 index 8f99a99..0000000 --- a/tmpfiles.conf +++ /dev/null @@ -1,5 +0,0 @@ -# -# /usr/lib/tmpfiles.d/arch.conf -# - -d /run/daemons 0755 root root - diff --git a/zsh-completion b/zsh-completion index d860e51..64cbc2a 100644 --- a/zsh-completion +++ b/zsh-completion @@ -18,10 +18,10 @@ _rc.d () { _arguments "*: :" ;; start) - _arguments "*: :($(comm -23 <(echo /etc/rc.d/*(N-*:t)|tr ' ' '\n') <(echo /run/daemons/*(N:t)|tr ' ' '\n')))" + _arguments "*: :($(comm -23 <(echo /etc/rc.d/*(N-*:t)|tr ' ' '\n') <(echo /sys/fs/cgroup/initscripts/daemons/*(N/:t)|tr ' ' '\n')))" ;; stop|restart|reload) - _arguments "*: :(/run/daemons/*(N:t))" + _arguments "*: :(/sys/fs/cgroup/initscripts/daemons/*(N/:t))" ;; *) _arguments "*: :(/etc/rc.d/*(N-*:t))" -- Sebastien "Seblu" Luttringer
On Tue, Jun 12, 2012 at 12:01 AM, Dave Reisner <d@falconindy.com> wrote:
On Mon, Jun 11, 2012 at 11:10:40PM +0200, Sébastien Luttringer wrote: So what do people who compile their own kernels without cgroups do? With this patch... swtich from century and use cgroup :p
I can rework it to support kernel with and without cgroup (with both hierarchies). Just let me know if you see a show stopper.
No need for a while loop here just to trim a string...
name=${name##+(!|@|-)}
Thank you! That 's what I was looking for! Your bash knowledge impresses me day by day.
+ *) break;; + esac + done + echo $name
Quote, please.
I doesn't see the benefits of quoting here. $ f() { a="toto toto" ; echo $a ; } $ g() { a="titi titi"; echo "$a"; } $ for i in $(f); do echo $i; done toto toto $ for i in $(g); do echo $i; done titi titi
+ stat_bkgd "${2^} $name"
This is the only place you sentence case a daemon name in the output. Intentional?
Yes we are starting daemon in background, so output formating from script is removed. Currently we output "Starting $name..." To keep it generic with others kind of call (restart, foo, bar) i only capitalize the first letter. Output become "Start $name" on startup.
+ exec_daemon /etc/rc.d/"$name" "$2" >/dev/null & + else + exec_daemon /etc/rc.d/"$name" "$2" + fi + ) + # stop action unregister and cleanup + if [[ $2 == stop ]]; then + kill_daemon "$1"
So that's it? We just call kill daemon here and don't even honor the script's own stop function anymore?
Stop function is honored by "exec_daemon stop" in previous lines.
OCD: Is it really too much to ask to write this as a proper if/then? sure.
After only 1/4 of a second you send the death touch onto all tasks? Go take a look at a service like squid or mysql that can survive at _least_ 5-10s after receiving a TERM. What about services that don't respond to a TERM, but would exit on a HUP? They're going to be invariably death touched. This is way too simple of a heuristic to be healthy.
Remember that "stop" script have been called before and have handled daemon shutdown correctly. If this function have process to kill, it's garbage collecting. I take this value from kill_all_wait() function.
+ printf "e.g: ${C_MAIN}rc.d ${1:-start} ${0##*/}${C_CLEAR}\n" >&2
Magic help messages which change text? Can't we just generalize it?
I don't understand what you mean. Thanks for your review i will include your suggestions and post a new patch asap. -- Sébastien "Seblu" Luttringer www.seblu.net
This no longer applies. On Mon, Jun 11, 2012 at 11:10 PM, Sébastien Luttringer <seblu@seblu.net> wrote:
From: Igor M Podlesny <for.poige+archlinux@gmail.com>
Signed-off-by: Sébastien Luttringer <seblu@seblu.net> --- rc.sysinit | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/rc.sysinit b/rc.sysinit index 58f3216..c276da7 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -42,9 +42,10 @@ if [[ ! -a /usr/lib ]] ; then printf "${C_FAIL}/usr is not mounted. This is not supported.${C_OTHER}\n" fi
-if ! grep -q devtmpfs /proc/filesystems; then - printf "${C_FAIL}Your kernel does not have devtmpfs support. This is not supported.${C_OTHER}\n" -fi +case $(< /proc/filesystems) in + *devtmpfs*) ;; + *) printf "${C_FAIL}Your kernel does not have devtmpfs support. This is not supported.${C_OTHER}\n" ;; +esac
HWCLOCK_PARAMS="--systz" case $HARDWARECLOCK in -- Sebastien "Seblu" Luttringer
participants (4)
-
Dave Reisner
-
Igor M Podlesny
-
Sébastien Luttringer
-
Tom Gundersen