2010-08-11 80 views
4

我有一個bash腳本多次調用MySQL。不必重新連接到MySQL,有沒有辦法保持連接打開?理想情況下,如果腳本提前退出,連接將關閉。我認爲命名管道可以工作,但他們會保持開放。如何保持在Bash中打開的MySQL連接

這裏是什麼,我希望能找到一個快速僞例如:


openMySQL 
executeMySQL "SELECT 1" 
exit 1 
executeMySQL "SELECT 2" 

我正在尋找的openMySQLexecuteMySQL功能在MySQL連接實際上會關閉exit 1期間。

+0

執行退出後??某種量子編程的東西?;-) – zerkms 2010-08-11 21:48:53

+0

使用MySQL殼和無論你想給它輸入。http://dev.mysql.com/doc/refman/ 5.1/en/mysql.html – msw 2010-08-11 21:52:08

回答

4

爲了我的理解你的問題:coproc's在zsh/ksh和bash v4 +中可用,可能與您的想法類似,例如,

bash4-4.1$ coproc MYSQL mysql -B -uroot 
[1] 10603 
bash4-4.1$ jobs 
[1]+ Running     coproc COPROC MYSQL mysql -B -uroot & 
bash4-4.1$ echo 'show databases;' | MYSQL 
Database 
information_schema 
... 

該命令被保持在後臺運行,其標準輸入/輸出可以訪問,就會完成(作爲結果的標準輸入關閉/ EOF荷蘭國際集團)只要電流殼存在...

6

我有我正在尋找的一部分。

使用FD = 3寫入保持MySQL的連接打開:

 

exec 3> >(mysql) 
echo "SELECT 1;" >&3 
echo "SELECT 2;" >&3 
exec 3>&- 
 

保持MySQL連接開放使用FD = 3閱讀:

 

exec 3< <(echo "SELECT 1;SELECT 2;"|mysql|sed '1d') 
while read <&3 
do 
    echo $REPLY 
done 
 

注:sed的 '1D' 刪除頭。

有什麼辦法可以合併這些,所以你可以寫入一個fd並從另一個讀取?

+2

> | mysql | sed'1d') 不要這樣做,用'mysql -N' – Igor 2016-07-30 18:32:26

3

我知道這個線程是舊的,但我也在尋找一個舒適的bash mysql會話實現,並沒有找到足夠滿足我的需求的東西,所以我寫了我自己的一個,我想分享一下世界。

############### BASIC MYSQL SESSION IMPLEMENTATION FOR BASH (by Norman 

Geist 2015) ############# 
# requires coproc, stdbuf, mysql 
#args: handle query 
function mysql_check { 
    local handle 
    handle=(${1//_/ }) 
    #has right structure && is still running && we opened it? 
    if [[ ${#handle[*]} == 3 ]] && ps -p ${handle[2]} 2>> /dev/null >> /dev/null && { echo "" >&${handle[1]}; } 2> /dev/null; then 
    return 0 
    fi 
    return 1 
} 

# open mysql connection 
#args: -u user [-H host] [-p passwd] -d db 
#returns $HANDLE 
function mysql_connect { 
    local argv argc user pass host db HANDLEID i 
    #prepare args 
    argv=($*) 
    argc=${#argv[*]} 

    #get options 
    user="" 
    pass="" 
    host="localhost" 
    db="" 
    for ((i=0; $i < $argc; i++)) 
    do 
    if [[ ${argv[$i]} == "-h" ]]; then 
     echo "Usage: -u user [-H host] [-p passwd] -d db" 
     return 0 
    elif [[ ${argv[$i]} == "-u" ]]; then 
     i=$[$i+1] 
     if [[ ${#argv[$i]} -gt 0 ]]; then 
    user=${argv[$i]} 
     else 
    echo "ERROR: -u expects argument!" 
    return 1 
     fi 
    elif [[ ${argv[$i]} == "-p" ]]; then 
     i=$[$i+1] 
     if [[ ${#argv[$i]} -gt 0 ]]; then 
    pass="-p"${argv[$i]} 
     else 
    echo "ERROR: -p expects argument!" 
    return 1 
     fi 
    elif [[ ${argv[$i]} == "-H" ]]; then 
     i=$[$i+1] 
     if [[ ${#argv[$i]} -gt 0 ]]; then 
    host=${argv[$i]} 
     else 
    echo "ERROR: -H expects argument!" 
    return 1 
     fi 
    elif [[ ${argv[$i]} == "-d" ]]; then 
     i=$[$i+1] 
     if [[ ${#argv[$i]} -gt 0 ]]; then 
    db=${argv[$i]} 
     else 
    echo "ERROR: -d expects argument!" 
    return 1 
     fi 
    fi 
    done 

    if [[ ${#user} -lt 1 || ${#db} -lt 1 ]]; then 
    echo "ERROR: Options -u user and -d db are required!" 
    return 1; 
    fi 

    #init connection and channels 
    #we do it in XML cause otherwise we can't detect the end of data and so would need a read timeout O_o 
    HANDLEID="MYSQL$RANDOM" 
    eval "coproc $HANDLEID { stdbuf -oL mysql -u $user $pass -h $host -D $db --force --unbuffered --xml -vvv 2>&1; }" 2> /dev/null 
    HANDLE=$(eval 'echo ${'${HANDLEID}'[0]}_${'${HANDLEID}'[1]}_${'${HANDLEID}'_PID}') 
    if mysql_check $HANDLE; then 
    export HANDLE 
    return 0 
    else 
    echo "ERROR: Connection failed to [email protected]$host->DB:$db!" 
    return 1 
    fi 
} 

#args: handle query 
#return: $DATA[0] = affected rows/number of sets; 
#  $DATA[1] = key=>values pairs following 
#  $DATA[2]key; DATA[3]=val ... 
function mysql_query { 
    local handle query affected line results_open row_open cols key val 
    if ! mysql_check $1; then 
    echo "ERROR: Connection not open!" 
    return 1 
    fi 
    handle=(${1//_/ }) 

    #delimit query; otherwise we block forever/timeout 
    query=$2 
    if [[ ! "$query" =~ \;\$ ]]; then 
    query="$query;" 
    fi 
    #send query 
    echo "$query" >&${handle[1]} 

    #get output 
    DATA=(); 
    DATA[0]=0 
    DATA[1]=0 
    results_open=0 
    row_open=0 
    cols=0 
    while read -t $MYSQL_READ_TIMEOUT -ru ${handle[0]} line 
    do 
    #WAS ERROR? 
    if [[ "$line" == *"ERROR"* ]]; then 
     echo "$line" 
     return 1 
    #WAS INSERT/UPDATE? 
    elif [[ "$line" == *"Query OK"* ]]; then 
     affected=$([[ "$line" =~ Query\ OK\,\ ([0-9]+)\ rows?\ affected ]] && echo ${BASH_REMATCH[1]}) 
     DATA[0]=$affected 
     export DATA 
     return 0 
    fi 

    #BEGIN OF RESULTS 
    if [[ $line =~ \<resultset ]]; then 
     results_open=1 
    fi 

    #RESULTS 
    if [[ $results_open == 1 ]]; then 
     if [[ $line =~ \<row ]]; then 
    row_open=1 
    cols=0 
     elif [[ $line =~ \<field && $row_open == 1 ]]; then 
    key=$([[ "$line" =~ name\=\"([^\"]+)\" ]] && echo ${BASH_REMATCH[1]}) 
    val=$([[ "$line" =~ \>(.*)\<\/ ]] && echo ${BASH_REMATCH[1]} || echo "NULL") 
    DATA[${#DATA[*]}]=$key 
    DATA[${#DATA[*]}]=$val 
    cols=$[$cols+1] 
     elif [[ $line =~ \<\/row ]]; then 
    row_open=0 
    DATA[0]=$[${DATA[0]}+1] 
    DATA[1]=$cols 
     fi 
    fi 

    #END OF RESULTS 
    if [[ $line =~ \<\/resultset ]]; then 
     export DATA 
     return 0 
    fi 
    done 
    #we can only get here 
    #if read times out O_o 
    echo "$FUNCNAME: Read timed out!" 
    return 1 
} 

#args: handle 
function mysql_close { 
    local handle 
    if ! mysql_check $1; then 
    echo "ERROR: Connection not open!" 
    return 1 
    fi 
    handle=(${1//_/ }) 
    echo "exit;" >&${handle[1]} 

    if ! mysql_check $1; then 
    return 0 
    else 
    echo "ERROR: Couldn't close connection!" 
    return 1 
    fi 
} 
############### END BASIC MYSQL SESSION IMPLEMENTATION FOR BASH ################################ 

# Example usage 
#define timeout for read command, in case of server error etc. 
export MYSQL_READ_TIMEOUT=10 

# Connect to db and get $HANDLE 
mysql_connect -u mydbuser -d mydb -H mydbserver 

#query db and get $DATA 
mysql_query $HANDLE "SELECT dt_whatever from tbl_lol WHERE dt_rofl=10" 

#close connection 
mysql_close $HANDLE 

注:

  • 節省$處理到一個新的變量之後,只要你喜歡
  • 不能交換的bash會話之間$手柄連接打開儘可能多的連接
  • 您需要linux軟件包「coproc」「stdbuf」「mysql」
  • 返回DATA是一個bash數組
$DATA[0] = affected rows/number of sets; 
$DATA[1] = number of key=>values pairs following; 
$DATA[2] = key1; 
$DATA[3] = value1; 
     [...] 
$DATA[n-1] = keyn; 
$DATA[n] = valuen; 
  • 一般來說,所有的查詢應該工作,甚至 「SELECT COUNT(*)」

示例如何循環的兩列查詢

如返回的數據。 「SELECT dt_id,dt_name FROM ...「

fields=2 
for ((i=2; $i<$((${DATA[0]}*${DATA[1]}*$fields)); i+=$((${DATA[1]}*$fields)))) 
do 
    field1key = ${DATA[$i]}; #this is "dt_id" 
    field1value = ${DATA[$i+1]}; #this is the value for dt_id 
    field2key = ${DATA[$i+2]}; #this is "dt_name" 
    field2value = ${DATA[$i+3]}; #this is the value for dt_name 
done 
相關問題