2013-02-25 90 views
1

我試圖創建一個bash腳本,它將同步指定爲遠程服務器(也由參數指定)的命令行參數的目錄。目前,我使用的是eval,它解決了參數擴展問題,但由於某種原因導致rsync不能保留遠程文件的所有權(除了Evil之外,我知道)。使用命令提示符下的所有標誌和參數運行rsync命令可以正常工作。從不保留所有權的bash腳本運行rsync

我嘗試使用$()作爲替代方案,但我與變量擴展和保護該保護需要用於遠程rsync的路徑(這需要用於與空格的路徑既引號反斜槓)的位一個真正的混亂。

所以 - 我想2個問題 - 是否有一個原因,eval阻止rsync從保留所有權(在bash腳本正在運行的源計算機上的根,和ING ssh到遠程機器根太 - 只爲現在)?有沒有辦法讓$()在這種情況下工作?該(修整)代碼如下:

#!/bin/bash 

RSYNC_CMD="/usr/bin/rsync" 
RSYNC_FLAGS="-az --rsh=\"/usr/bin/ssh -i \${DST_KEY}\"" # Protect ${DST_KEY} until it is assigned later 

SRC=${1} # Normally this is sense checked and processed to be a canonical path 

# Logic for setting DST based on command line parameter snipped for clarity - just directly assign for testing 

DST='[email protected]:' 
DST_KEY='/path/to/sshKey.rsa' 

TARG=${DST}${SRC//' '/'\ '} # Escape whitespace for target system 

eval ${RSYNC_CMD} ${RSYNC_FLAGS} \"${SRC}\" \"${TARG}\" # Put quotes round the paths - even though ${TARG} is already escaped 

# All synced OK - but ownership not preserved despite -a flag 

我試圖改變RSYNC_CMDsudo /usr/bin/rsync,並且還加入--rsync-path="sudo /usr/bin/rsyncRSYNC_FLAGS,但沒有取得任何區別。我只是看不到我失蹤的東西...

+0

'rsync --help | grep owner'告訴我:'-o,--owner保存所有者(僅限超級用戶)''。你嘗試過這個選項嗎? – Bobby 2013-02-25 15:54:56

+0

謝謝 - 正如@chepner下面所說的,-a意味着-o,如果我從命令行執行它,它工作正常,所以我推測這是eval(只是可以肯定的是,我確實嘗試了-o,但沒有區別)。我將在接下來的幾天裏給chepner改寫一下。 – dsl101 2013-02-26 17:25:50

回答

1

正確的做法是使用數組。 -a應該暗示-o

RSYNC_CMD="/usr/bin/rsync" 

DST='[email protected]:' 
DST_KEY='/path/to/sshKey.rsa' 

RSYNC_FLAGS=(-az --rsh="/usr/bin/ssh -i ${DST_KEY}") 

SRC=${1} 
TARG="${DST}$SRC" 

${RSYNC_CMD} "${RSYNC_FLAGS[@]}" "${SRC}" "${TARG}" 

使用的RSYNC_RSH代替--rsh,你可以設置它的值之前導出該變量。這至少可以讓你把輸出放在你設置其餘標誌的相同區域。然後,您可以推遲完成其價值,直到您擁有正確的身份文件。

RSYNC_CMD="/usr/bin/rsync" 
export RSYNC_RSH="/usr/bin/ssh -i %s" # Use a placeholder for now; set it later 
RSYNC_FLAGS=(-a -z) 

# Later... 

DST='[email protected]:' 
DST_KEY='/path/to/sshKey.rsa' 
RSYNC_RSH=$(printf "$RSYNC_RSH" "$DST_KEY") 


SRC=${1} 
TARG="${DST}$SRC" 

${RSYNC_CMD} "${RSYNC_FLAGS[@]}" "${SRC}" "${TARG}" 
+0

謝謝 - 我離開了幾天,所以不能直接嘗試,但同時,是否可以在*'RSYNC_FLAGS'之後設置'DST_KEY' *,就像在我的原始代碼中使用您的方法一樣?我喜歡在頂部定義所有的標誌,但是這個需要包含計算出來的'DST_KEY' - 然後根據需要擴展'eval'。 – dsl101 2013-02-26 17:30:59

+0

我不建議使用'eval',因爲這可能會帶來安全風險。另一個選擇是使用'RSYNC_RSH'環境變量。它仍然需要在此過程中稍後設置它的值,但我會以「乾淨」的方式更新我的答案。 – chepner 2013-02-26 17:38:57

+0

更新有點難看。什麼決定了'DST_KEY'的價值?可以在'.ssh/config'中設置特定於站點的標識文件;那麼你根本不需要'si'的'-i'標誌。 – chepner 2013-02-26 18:03:59