[英]bash script not executing mysql command with values passed as variables
我正在修改一組處理視頻文件並將處理步驟報告給 mysql 數據庫的 bash 腳本(這是有問題的原始代碼)。
執行數據庫報告的函數是從主處理腳本中調用的,在原始腳本中如下所示:
_report_to_db(){
if [ "${REPORT_TO_DB}" = "Y" ] ; then
echo "INSERT IGNORE INTO tableA (objectIdentifierValue,object_LastTouched) VALUES ('${MEDIA_ID}',NOW()) ON DUPLICATE KEY UPDATE object_LastTouched = NOW()" | mysql --login-path="${LOGIN_PROFILE}" "${DB_NAME}" 2> /dev/null
_db_error_check
fi
}
由於腳本旨在直接從命令行運行,因此當您以這種方式運行它們時,它可以正常工作。 但是我正在通過 php 從 Web 界面運行它們,並且在引用/轉義空格和/或變量時有一些惡作劇。
例如,腳本在...| mysql
之后的空格處中斷...| mysql
...| mysql
並且它認為我試圖在沒有密碼的情況下以 root 身份運行 mysql 並完全忽略--login-path
和我正在向它傳遞的其他內容。
當我從這樣的變量調用mysql
:
_report_to_db(){
if [ "${REPORT_TO_DB}" = "Y" ] ; then
SQL_ARRAY=(INSERT IGNORE INTO tableA (columnA,lastTouched) VALUES ("${SOME_PASSED_VALUE}",NOW()) ON DUPLICATE KEY UPDATE object_LastTouched = NOW();)
MYSQL_COMMAND_ARRAY=(mysql --login-path="${LOGIN_PROFILE}" -e "${SQL_ARRAY[@]}" "${DB_NAME}")
echo "$(${MYSQL_COMMAND_ARRAY[@]})"
_db_error_check
fi
}
...我能夠正確登錄到 mysql,但 SQL 查詢被忽略(當它echo
是結果時,您將獲得標准的 MySQL --help
輸出。
到目前為止,我已經嘗試了各種引用、轉義、將查詢作為單獨的字符串變量引用、作為數組(如您所見)的各種變體。
同樣沒有幫助的是原始_db_error_check()
函數只檢查管道退出狀態的值。 因此,如果管道沒問題,但在路徑更遠的地方出現問題,它會默默地失敗。
_db_error_check(){
if [ "$?" != "0" ] ; then
# reports an error if the pipe exit value ≠ 0
else
# everything is ok! even if there was a mysql error
fi
}
這不是文件或數據庫權限問題(已經三重檢查了)。 有沒有我遺漏的引號或其他一些愚蠢的東西? 謝謝! 哦,我正在運行 OSX El Capitan。
更新
大聲笑,我打算發布調用腳本的 PHP,然后我想起 PHP 實際上正在調用一個 Pyhton 腳本,它也執行一些其他處理,這就是調用 bash 腳本的原因。 一切都在這里:
PHP
$command = escapeshellcmd("/usr/local/bin/python3 /Users/user/path/to/ingest.py " . $user . " 2>&1");
while (@ ob_end_flush());
$proc = popen($command, 'r');
echo '<pre>';
while (!feof($proc))
{
echo fread($proc, 4096);
@ flush();
}
echo '</pre>';
PYTHON
for item in os.listdir(ingestDir):
if not item.startswith("."):
filePath = os.path.abspath(ingestDir+"/"+item)
fileNameForMediaID = os.path.splitext(item)[0]
try:
ingest = subprocess.Popen(['/usr/local/bin/ingestfile','-e','-u',user,'-I',filePath,'-m',fileNameForMediaID])
ingest.wait()
os.remove(filePath)
except IOError as err:
print("OS error: {0}".format(err))
更新 2
我認為這實際上可能是我安裝的一個奇怪的怪癖(去圖)。 在主機上的 shell 中使用mysql --login-path=myDbUser [etc...]
我不斷收到錯誤ERROR 1045 (28000): Access denied for user 'ADMIN'@'localhost' (using password: NO)
客戶端用戶是ADMIN
並且我嘗試以myDbUser
身份登錄。
我實際上卸載並重新安裝了 mysql (通過 Homebrew)並且仍然有相同的結果。 使用不同的機器(運行 Sierra,但相同的 mysql 版本)我可以成功運行上述 shell 命令並以目標用戶身份登錄 mysql。
同樣在主機上,我可以sudo -u _www zsh
並以 Apache 用戶(即運行整個節目的用戶)身份運行命令,沒有問題。 那么為什么它既不能在腳本中正確運行,也不能以我的主要客戶端用戶身份從 Shell 中正確運行???
有任何想法嗎? $PATH
在上述所有情況下都是相同的。 相同的~/.mylogin.cnf
設置。 還有什么愚蠢的明顯我錯過了嗎?
您需要在此處使用間接擴展:
echo "$(${MYSQL_COMMAND_ARRAY[@]})"
如果參數的第一個字符是感嘆號 (!),並且參數不是 nameref,則它引入了一個變量間接級別。 Bash 使用由參數的其余部分形成的變量的值作為變量的名稱; 這個變量然后被擴展,並且該值用於替換的其余部分,而不是參數本身的值。 這稱為間接擴展。 如果 parameter 是 nameref,這將擴展為 parameter 引用的變量的名稱,而不是執行完整的間接擴展。 例外情況是下面描述的 ${!prefix*} 和 ${!name[@]} 的擴展。 感嘆號必須緊跟在左大括號之后才能引入間接性。
${!name[@]} ${!name[*]}
如果 name 是一個數組變量,則擴展到 name 中分配的數組索引(鍵)列表。 如果 name 不是數組,則在設置 name 時擴展為 0,否則為 null。 當使用 '@' 並且擴展出現在雙引號內時,每個鍵都擴展為一個單獨的詞。
PS:如果我可以提出一個我個人的意見,有一個 php -> python -> bash 鏈是你見過的最糟糕的編碼風格,你可能想把它改寫成單語,這樣會更容易至少追蹤進一步的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.