2012-08-03 57 views
1

我正在使用bash腳本來啓動puppet客戶端的雲服務器,以便我可以創建啓動映像,但是我從一個簡單的「cp -r」中獲取了奇怪的行爲,其中源代碼目錄的內容正在被複制,但父目錄不被複制。例如,如果我有/ root/puppet/file1,並且我在我的bash腳本中發出了一個cp -r /root/puppet /opt命令,而不是獲取/ opt/puppet/file1,我得到/ opt/file1。但是,如果我在腳本執行之前回應了腳本中的命令,然後複製該回顯的輸出並在命令行上運行它,那麼我會按預期方式獲取/ opt/puppet/file1。「cp -r」在bash中表現怪異嗎?

這是我的目錄結構。

mydirectory 
    - script.sh 
    - assets 
     - puppet 
      - file1 
      - file2 
      - file3 

下面是從我的腳本片段

#!/bin/bash 

### VARIABLE INITIALIZATION 
BOOTSTRAP_DIR="/opt/bootstrapping" 

# Die with an error message 
die() 
{ 
    echo "**** BOOTSTRAPPING FAILED ****" 
    echo -e "ERROR: ${2}" 
    exit ${1} 
} 

# check the return code of the previous command and die if != 0 
check_errs() 
{ 
    if [ "${1}" -ne "0" ]; then 
     die ${1} "${2}" 
    fi 
} 

# Get the path of the directory from which this script is being executed 
SCRIPT_PATH="`dirname \"$0\"`"    # relative 
check_errs $? "Could not get the relative path of the executing script" 
SCRIPT_PATH="`(cd \"$SCRIPT_PATH\" && pwd)`" # absolutized and normalized 
check_errs $? "Could not get the absolute path of the executing script" 

### DEPLOY THE BOOTSTRAPPING FILES 
if [ -d "${BOOTSTRAP_DIR}" ]; then 
    echo "Removing ${BOOTSTRAP_DIR}" 
    rm -rf ${BOOTSTRAP_DIR} 
    check_errs $? "Could not remove ${BOOTSTRAP_DIR}" 
fi 

if [ ! -d "${SCRIPT_PATH}/assets/puppet" ]; then 
    die 1 "Can not find ${SCRIPT_PATH}/assets/puppet" 
fi 

if [ ! -f "${SCRIPT_PATH}/assets/rc.local" ]; then 
    die 1 "Can not find ${SCRIPT_PATH}/assets/rc.local" 
fi 

# This command succeeds, but /opt/bootstrapping/puppet does not exist afterwards. 
# Instead I get /opt/bootstrapping/files... 
echo "Copying ${SCRIPT_PATH}/assets/puppet to ${BOOTSTRAP_DIR}" 
cp -r ${SCRIPT_PATH}/assets/puppet ${BOOTSTRAP_DIR} 
check_errs $? "Could not copy ${SCRIPT_PATH}/assets/puppet to ${BOOTSTRAP_DIR}" 

echo "Copying ${SCRIPT_PATH}/assets/rc.local to /etc/rc.local" 
cp ${SCRIPT_PATH}/assets/rc.local /etc/rc.local 
check_errs $? "Could not copy ${SCRIPT_PATH}/assets/rc.local to /etc/rc.local" 

任何人都可以解釋爲什麼只有我的源目錄的內容被複制?我覺得這是愚蠢的,我沒有看到,因爲我很累。

編輯

這肯定是我啞巴的情況。當腳本調用cp -r /root/assets/puppet /opt/bootstrapping時,/ opt/bootstrapping不存在,因此cp將創建/ opt/bootstrapping,並將源文件放入該新目錄中。我認爲這個問題將來對任何人都不會有太大的價值。除非有人反對,否則我想刪除它。

+3

'cp'是一個可執行文件,而不是shell內置的。因此無論您使用的是哪個shell,'cp -r'的行爲都是相同的。 – 2012-08-03 03:37:12

+0

但它的表現不一樣。如果我回應命令,我會得到'cp -r/root/assets/puppet/opt/bootstrapping'這就是腳本應該執行的內容。當我在腳本之外運行它時,目錄會被複制,而不僅僅是文件。 – GregB 2012-08-03 03:41:41

+0

Acutally,有時'cp'別名是別的。你可以運行別名|從bash提示符輸入grep cp'並告訴我們你得到了什麼? – 2012-08-03 03:50:38

回答

1

在OS X 10.7,爲CP手冊頁說:

-R If source_file designates a directory, cp copies the directory and the entire subtree connected at that 
     point. If the source_file ends in a /, the contents of the directory are copied rather than the directory 
     itself. This option also causes symbolic links to be copied, rather than indirected through, and for cp to 
     create special files rather than copying them as normal files. Created directories have the same mode as 
     the corresponding source directory, unmodified by the process' umask. 

注意,選項實際上是記錄爲-R而不是-r但兩者的工作。

我試圖在某些目錄中的以下內容:

mkdir -p tmp1/tmp2/tmp3 
mkdir test 
cp -r tmp1 test 

和它的作品如你所期望的,即測試現在包含tmp1和它的子目錄。你能告訴我們關於你正在使用的操作系統的更多細節嗎?另外,你是否檢查過你的系統是否有非標準的cp?

+0

該選項記錄爲「-R」,因爲它與「-r」不同:「cp實用程序的歷史版本有-r選項。此實現支持該選項;但強烈建議不要使用該選項, 不正確地複製特殊文件,符號鏈接或fifo。「 – 2012-08-03 03:49:55

+0

我已經嘗試了-r和-R,並且看到了相同的行爲。 – GregB 2012-08-03 03:51:12

+0

我正在運行Ubuntu 10.04 LTS並使用股票cp。 – GregB 2012-08-03 03:51:33