1. 程式人生 > >shell采坑之旅--變量$PWD引發的血案

shell采坑之旅--變量$PWD引發的血案

shell linux oracle

背景:
分組自研的數據庫審計平臺已在windows環境下,實現了一鍵拉取Oracle數據庫性能報告的功能。
最近接到審計平臺開發的小任務:將windows環境下實現一鍵拉取oracle數據庫性能報告的bat腳本改為linux下的
shell腳本。
腳本改寫的很快,三百多行的bat腳本,半天就改寫成了shell,接下來就是最痛苦的測試環節了。

踩坑開始:
bat腳本在定義變量時,將連接數據庫的密碼定義為名為PWD的變量(如下),踩坑由此開始。。。

@echo off
...
set PWD=xxx
...

我在定義連接oracle的用戶密碼時,便參照bat腳本,仍使用PWD作為密碼變量:

#################setting variables######################
。
。
TNS=dbname
PWD=pass1234
。
。
#################Making gather&scan Files######################
。
。
sqlplus dbaudit/$PWD@$TNS <<EOF >>sqlplus.log          --第1部分
here is command1!
EOF
。
。
#################Spooling Reports######################
cd $SHELL_PATH/$1
echo -e "Spooling Reports..."
for(( i = 0; i < 10; i++ ))  
do  
{                              
    sqlplus dbaudit/$PWD@$TNS <<EOF >>sqlplus.log      --第2部分
    here is command2!
    EOF
}&  
done  
wait 
。
。

為了拉取oracle報告,在腳本中有多次連接數據庫的操作:

sqlplus username/$PWD@$TNS <<EOF >>sqlplus.log
...
EOF

腳本看起來毫無破綻,可是執行時第1部分的sqlplus命令時,可以成功連接數據庫,並執行相關操作;而執行到腳本第2部分的sqlplus命令時,卻總是報sqlplus的語法錯誤!
這是為何呢?!
思來想去無果,百度是不可能有結果了,因為報錯很直白,就是sqlplus語法不對。

Spooling Reports...

SQL*Plus: Release 11.2.0.1.0 Production on Thu May 17 12:28:13 2018

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

SQL*Plus: Release 11.2.0.1.0 Production

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Use SQL*Plus to execute SQL, PL/SQL and SQL*Plus statements.

Usage 1: sqlplus -H | -V

    -H             Displays the SQL*Plus version and the
                   usage help.
    -V             Displays the SQL*Plus version.

Usage 2: sqlplus [ [<option>] [{logon | /nolog}] [<start>] ]

於是,將變量部分和報錯部分的腳本提取出,寫在test.sh中單獨執行,邪門的事情發生了,執行過程很成功!
奇怪了,腳本前後同樣的命令,前面的成功,後面的失敗了,why?!
仔細閱讀腳本,中間只有一次“cd $SHELL_PATH/$1”的命令,難道是這個命令導致的?不應該呀!

繼續將報錯腳本拿出來單獨執行,一次偶然的"echo $PWD"揭示了真相!

[padba@cnsz081003 ~]$ echo $PWD
/paic/dba/tmp/padba

納尼!PWD居然是linux系統自帶的變量,而且顯示的就是當前目錄!

於是推斷,在執行“cd $SHELL_PATH/$1”這樣的change directory命令後,系統的PWD變量覆蓋了腳本開始時

定義的PWD=pass1234,也就是說,在切換目錄後,PWD的值就不是"pass1234"了,而是一個目錄,也就是"$SHELL_PATH/$1"對應的值!

驗證推斷:

[padba@cnsz081003 ~]$ export PWD=pass1234   --手動定義PWD變量
[padba@cnsz081003 pass1234]$ echo $PWD
pass1234                                    --顯示PWD變量值為pass1234,沒毛病!
[padba@cnsz081003 pass1234]$ cd             --切換目錄
[padba@cnsz081003 ~]$ echo $PWD
/paic/dba/tmp/padba                         --PWD的值變為當前目錄!

至此,真相大白!
修改腳本中的PWD為PASSWD後,報錯消失,腳本順利完成拉取報告的使命!

總結:
linux中有許多類似$PWD這類的變量,我們在腳本中定義變量名時,要避開系統自帶的變量名,否則會導致灰常奇怪且讓人欲罷不能的ERROR!

shell采坑之旅--變量$PWD引發的血案