0

次のスクリプトに出くわしましたが、完全に理解できないことがあります

    #!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org

START=50

start() {
        mkdir -m 0755 -p /var/run/vsftpd
        service_start /usr/sbin/vsftpd
}

stop() {
        service_stop /usr/sbin/vsftpd
}

ここで「/etc/rc.common」はどのように使用されますか?

ここにrc.commonの内容があります

#!/bin/sh
# Copyright (C) 2006-2011 OpenWrt.org

. $IPKG_INSTROOT/lib/functions.sh
. $IPKG_INSTROOT/lib/functions/service.sh

initscript=$1
action=${2:-help}
shift 2

start() {
        return 0
}

stop() {
        return 0
}

reload() {
        return 1
}

restart() {
        trap '' TERM
        stop "$@"
        start "$@"
}

boot() {
        start "$@"
}

shutdown() {
        stop
}

disable() {
        name="$(basename "${initscript}")"
        rm -f "$IPKG_INSTROOT"/etc/rc.d/S??$name
        rm -f "$IPKG_INSTROOT"/etc/rc.d/K??$name
}

enable() {
        name="$(basename "${initscript}")"
        disable
        [ -n "$START" -o -n "$STOP" ] || {
                echo "/etc/init.d/$name does not have a START or STOP value"
                return 1
        }
        [ "$START" ] && ln -s "../init.d/$name" "$IPKG_INSTROOT/etc/rc.d/S${START}${name##S[0-9][0-9]}"
        [ "$STOP"  ] && ln -s "../init.d/$name" "$IPKG_INSTROOT/etc/rc.d/K${STOP}${name##K[0-9][0-9]}"
}

enabled() {
        name="$(basename "${initscript}")"
        [ -x "$IPKG_INSTROOT/etc/rc.d/S${START}${name##S[0-9][0-9]}" ]
}

depends() {
        return 0
}

help() {
        cat <<EOF
Syntax: $initscript [command]

Available commands:
        start   Start the service
        stop    Stop the service
        restart Restart the service
        reload  Reload configuration files (or restart if that fails)
        enable  Enable service autostart
        disable Disable service autostart
$EXTRA_HELP
EOF
}

. "$initscript"

ALL_COMMANDS="start stop reload restart boot shutdown enable disable enabled depends ${EXTRA_COMMANDS}"
list_contains ALL_COMMANDS "$action" || action=help
[ "$action" = "reload" ] && action='eval reload "$@" || restart "$@" && :'
$action "$@"

あなたの何人かがこれに光を当ててくれることを願っています。ありがとうございました!

PS:もう 1 つよくわからないのは、スタートアップ スクリプトのフル パスに関数名を追加するだけで、スクリプト内の関数がどのように呼び出されるかということです。たとえば、「/etc/init.d/vsftpd test」は、/etc/init.d/vsftpd または /etc/rc.common のいずれかで「test」という名前の関数を実行します。ただし、「test」関数が両方で定義されている場合起動スクリプトと /etc/rc.common の場合、前者の関数は実行されますが、rc.common の関数は実行されません。

また、そうでない理由

'[ "$action" = "reload" ] && action='eval reload "$@" || restart "$@" && :'

単純に次のように記述

'[ "$action" = "reload" ] && action='eval reload "$@" || restart "$@"'

ありがとうございました!

4

1 に答える 1

2

execve(2)かなり最新の Linux システムから:

通訳スクリプト

インタープリター スクリプトは、実行権限が有効になっているテキスト ファイルであり、その最初の行は次の形式です。

#! interpreter [optional-arg]

インタープリターは、それ自体がスクリプトではない実行可能ファイルの有効なパス名でなければなりません。execve() のファイル名引数がインタープリター スクリプトを指定する場合、インタープリターは次の引数で呼び出されます。

interpreter [optional-arg] filename arg...

arg... は、 の argv 引数が指す一連の単語です execve()

移植可能な使用のために、optional-arg は存在しないか、単一の単語として指定する必要があります (つまり、空白を含めないでください)。[...]

#!/bin/sh filenameこのイディオムを使ったスクリプトはあまり見たことがありません。使い方がややこしいと思います。

おそらく、簡単なテストで説明できます。これらのファイルは /tmp/test に存在する必要があります。これは、test_interpreter.sh のインタープリター行の詳細を考えると、この場合に重要です。

「#!」で指定されたスクリプト 行 (rc_interpreter_line) は、最初に呼び出されたスクリプトでコマンドを実行するように調整します。これは、sourcing_script 変数とシフト コマンドを使用して行います。質問で引用したコードは、この連鎖のかなり複雑なバージョンを実行します。この種の連鎖がなければ、インタプリタ行で指定されたファイルだけが実行されます。

rc_interpreter_line の内容

echo '===='
echo $0 "$@"

TESTVAR=set

sourcing_script=$1
shift

. "$sourcing_script" "$@"

echo '===='

test_interpreter.sh の内容

#!/bin/sh /tmp/test/rc_interpreter_line

echo '-----'
echo "My file name is test_interpreter.sh, but \$0 is $0"

echo Command line: $0 "$@"

echo "TESTVAR is '$TESTVAR'"
echo '-----'

exit 0

権限:

sh-4.2$ ls -l
total 8
-rw-r--r-- 1 dev dev 104 Aug 24 13:36 rc_interpreter_line
-rwxr-xr-x 1 dev dev 191 Aug 24 13:36 test_interpreter.sh

サンプルラン。最初に test_interpreter.sh を直接実行します。

sh-4.2$ ./test_interpreter.sh -opt arg1 arg2
====
/tmp/test/rc_interpreter_line ./test_interpreter.sh -opt arg1 arg2
-----
My file name is test_interpreter.sh, but $0 is /tmp/test/rc_interpreter_line
Command line: /tmp/test/rc_interpreter_line -opt arg1 arg2
TESTVAR is 'set'
-----

2 つ目は、より単純にシェルを呼び出します。動作が起動しないexecve(2)ため、このシェルの実行では、最初の行をコメントとして扱い、test_interpreter.sh 内のコマンドを実行するだけです。

sh-4.2$ sh test_interpreter.sh -opt arg1 arg2
-----
My file name is test_interpreter.sh, but $0 is test_interpreter.sh
Command line: test_interpreter.sh -opt arg1 arg2
TESTVAR is ''
-----

しかし、私の個人的な好みは、イディオムを完全に避けることです。次のようなスクリプトの早い段階でコマンドを使用する方がはるかに明確です。

. /etc/rc.common

...「面白い」「#!」に頼るのではなく ./my_scriptとを使用すると、異なる動作が作成されます。sh my_script

于 2013-08-24T19:11:05.550 に答える