2013-08-24 76 views
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 "[email protected]" 
     start "[email protected]" 
} 

boot() { 
     start "[email protected]" 
} 

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 "[email protected]" || restart "[email protected]" && :' 
$action "[email protected]" 

希望你們中的一些可以在此揭示的內容。謝謝!

PS:另一件我不太清楚的事情是腳本中的函數是如何通過簡單地將函數名追加到啓動腳本的完整路徑來調用的。例如,'/etc/init.d/vsftpd test'將在/etc/init.d/vsftpd或/etc/rc.common.But中執行名爲'test'的函數,如果'test'函數在啓動腳本和/etc/rc.common,前者中的函數將運行,而rc.common中的函數不運行。

另外,爲什麼不

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

簡寫成

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

謝謝!

+0

是您的第一個示例整個腳本? – lurker

+0

是的,我剛剛隨機挑選了一個簡單的!所有的啓動腳本共享相同的開始行#!/ bin/sh /etc/rc.common – benson

+0

在文件開頭的「hash bang」可以爲解釋器提供可選的參數。所以一般來說你可以使用'#!/ usr/bin/sh [options]'。但是腳本文件並不被認爲是shell的「選項」,我還沒有看到以這種方式提供shell腳本作爲參數的情況。我在'bash'中做了一個快速測試用例,並沒有觀察到有用的行爲(即'bash'忽略了可選的腳本文件名參數)。您的'rc.common'文件展示了一種包含另一個腳本的正確方法(以點('.')開頭)「。 – lurker

回答

1

execve(2)相當當前的Linux系統上:

解釋腳本

解釋型的腳本是具有執行權限 啓用一個文本文件,其第一行的形式爲:

#! interpreter [optional-arg] 

解釋器必須是可執行文件的有效路徑名,該可執行文件是 本身不是一個腳本。如果調用execve的文件名參數()指定 解釋型的腳本,然後解釋將與 以下參數調用:

interpreter [optional-arg] filename arg... 

其中arg ...是該系列的話由 的argv的說法指出, execve()

對於便攜式應用,可選參數應該不存在,或者被指定爲單個詞(即,它不應該包含空格) ; [...]

我還沒有看到很多使用#!/bin/sh filename成語的腳本。我覺得它的使用令人困惑。

也許一個簡單的測試將說明。這些文件應該存在於/ tmp/test中,在這種情況下,考慮到test_interpreter.sh中的解釋器行的細節,這很重要。

在「#!」中命名的腳本行(rc_interpreter_line)安排在最初調用的腳本中運行命令,我通過sourcing_script變量和shift命令執行命令。你在問題中引用的代碼是一個相當複雜的鏈接版本。沒有這種鏈接,所有運行的都是在解釋器行中命名的文件。

內容rc_interpreter_line的

echo '====' 
echo $0 "[email protected]" 

TESTVAR=set 

sourcing_script=$1 
shift 

. "$sourcing_script" "[email protected]" 

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 "[email protected]" 

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' 
----- 

第二個調用shell更清楚。沒有execve(2)行爲觸發,所以這個shell的運行只是運行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_scriptsh my_script

+0

感謝您的詳細回覆!但我仍然不明白如何通過將函數名稱附加到啓動腳本的完整路徑來調用腳本中的函數。例如,'/etc/init.d/vsftpd test'將在/etc/init.d/vsftpd或/etc/rc.common.Thanks中執行名爲'test'的函數! – benson