जाँच करें कि क्या डेटाबेस शेल का उपयोग करके पोस्टग्रेक्यूएल में मौजूद है


130

मैं सोच रहा था कि क्या कोई मुझे इस बारे में बता पाएगा कि क्या PostgreSQL डेटाबेस मौजूद है या नहीं, यह जांचने के लिए शेल का उपयोग करना संभव है?

मैं एक शेल स्क्रिप्ट बना रहा हूं और मैं केवल यह चाहता हूं कि अगर यह पहले से मौजूद नहीं है तो डेटाबेस बनाना है लेकिन अब तक यह नहीं देखा गया है कि इसे कैसे लागू किया जाए।

जवाबों:


199

मैं Arturo के समाधान के निम्नलिखित संशोधन का उपयोग करता हूं:

psql -lqt | cut -d \| -f 1 | grep -qw <db_name>


यह क्या करता है

psql -l निम्नलिखित की तरह कुछ आउटपुट:

                                        List of databases
     Name  |   Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+-----------+----------+------------+------------+-----------------------
 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
(4 rows)

भोले दृष्टिकोण का उपयोग करने का मतलब है कि "सूची," एक्सेस "या" पंक्तियों "नामक एक डेटाबेस की खोज सफल होगी। इसलिए हम इस आउटपुट को अंतर्निहित कमांड लाइन टूल के एक गुच्छा के माध्यम से केवल पहले कॉलम में खोजते हैं।


-tझंडा शीर्षलेख और पादलेख निकालता है:

 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres

अगले बिट, cut -d \| -f 1ऊर्ध्वाधर पाइप |चरित्र द्वारा आउटपुट को विभाजित करता है (बैकस्लैश के साथ शेल से बच जाता है), और फ़ील्ड 1 का चयन करता है। यह पत्ते:

 my_db             
 postgres          
 template0         

 template1         

grep -wयदि आप tempइस परिदृश्य में खोज कर रहे हैं तो पूरे शब्दों से मेल खाता है, और इसलिए मेल नहीं खाएगा । -qविकल्प, किसी भी उत्पादन स्क्रीन के लिए लिखा दबा देता, इसलिए यदि आप एक कमांड प्रॉम्प्ट आप को बाहर करने के साथ हो सकता है पर सहभागी इस चलाना चाहते हैं -qतुरंत तो कुछ प्रदर्शित किया जाता।

ध्यान दें कि grep -wअल्फ़ान्यूमेरिक, अंकों और अंडरस्कोर से मेल खाता है, जो कि पोस्टग्रैस्कल में अनछुए डेटाबेस नामों में अनुमत वर्णों का समूह है (हाइफ़न, अनियोजित पहचानकर्ताओं में कानूनी नहीं हैं)। यदि आप अन्य वर्णों का उपयोग कर रहे हैं, grep -wतो आपके लिए काम नहीं करेगा।


इस पूरे पाइपलाइन की निकास स्थिति 0(सफलता) होगी यदि डेटाबेस मौजूद है या 1(विफलता) अगर यह नहीं है। आपका शेल विशेष चर $?को अंतिम कमांड की निकास स्थिति में सेट करेगा । आप सशर्त में सीधे स्थिति का परीक्षण कर सकते हैं:

if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
    # database exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi

8
आप ... | grep 0शेल रिटर्न मान बनाने के लिए भी जोड़ सकते हैं यदि DB मौजूद नहीं है और 1 यदि ऐसा करता है; या ... | grep 1विपरीत व्यवहार के लिए
acjay

2
@ acjohnson55 और भी बेहतर: wcपूरी तरह से छोड़ दें । मेरा संशोधन देखिए। (आप बाहर निकलने स्थिति को पलटने के लिए चाहते हैं, बैश एक धमाके के ऑपरेटर का समर्थन करता है: ! psql ...)
BENESCH

अभी इसे देखकर अच्छा लगा
vol7ron

1
wcआदेश को छोड़ने के लिए सुझाव देने के लिए आगे , मैं उपयोग करूंगा grep -qw <term>। यह 0एक मैच और 1अन्यथा होने पर शेल को वापस करने का कारण होगा । फिर, $?इसमें रिटर्न वैल्यू होगी और आप इसका उपयोग करके यह तय कर सकते हैं कि आगे क्या करना है। इसलिए, मैं wcइस मामले में उपयोग नहीं करने की सलाह देता हूं । grepआप की जरूरत है क्या करेंगे
मैट फ्रेडमैन

मुझे आपकी प्रतिक्रिया के आधार पर इस उत्तर को अपडेट करने के लिए मिला। सबको शुक्रीया।
किबिबू

81

निम्नलिखित शेल कोड मेरे लिए काम करता है:

if [ "$( psql -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" )" = '1' ]
then
    echo "Database already exists"
else
    echo "Database does not exist"
fi

1
मुझे पसंद है कि आप किसी भी बाहरी कटौती grep wc और सामान पर रिले नहीं करते हैं .. आप db अस्तित्व की जांच करते हैं, जिसका मतलब है कि आपके पास कम से कम psql है, तो एंटी कम से कम और केवल आपके द्वारा उपयोग की जाने वाली कमांड है! वाकई बहूत बढिया। विषय के अलावा शेल प्रकार और न ही कमांड संस्करण या डिस्ट्रो का उल्लेख नहीं किया है .. मैं पाइप के ऐसे ढेर पर रिले नहीं करूँगा सिस्टम टूलींग के लिए जिसे मैंने जानने के लिए अन्य उत्तरों पर देखा है। यह वर्षों के बाद के मुद्दों की ओर जाता है
रिकार्डो मैनफ्रिन

1
मैं @RiccardoManfrin से सहमत हूं यह अधिक प्रत्यक्ष समाधान की तरह लगता है।
ट्रैविस

यदि आपको गैर पोस्टग्रेज उपयोगकर्ता के साथ ऐसा करने की आवश्यकता है, तो आप -U उपयोगकर्ता को जोड़ सकते हैं, लेकिन कनेक्ट करने के लिए एक डेटाबेस को सूचीबद्ध करना होगा, क्योंकि कोई भी मौजूद नहीं हो सकता है आप पोस्टग्रेज टेम्पलेट 1 डेटाबेस का उपयोग कर सकते हैं जो हमेशा मौजूद रहता है: psql -U user -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" template1
jun

साइबरविन psql में आउटपुट के लिए अजीब नियंत्रण वर्ण जोड़ता है ('1 \ C-M') और किसी को यह जांचने की आवश्यकता है कि क्या आउटपुट केवल 1 से शुरू होता है:if [[ $(...) == 1* ]]
jan

28
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l

यदि डेटाबेस निर्दिष्ट मौजूद है या 0 अन्यथा तो यह 1 वापस आ जाएगा।

यदि आप पहले से मौजूद डेटाबेस बनाने का प्रयास करते हैं, तो postgresql इस तरह से एक त्रुटि संदेश लौटाएगा:

postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists

10
पहला सुझाव बहुत खतरनाक है। क्या होगा exact_dbname_testमौजूद? परीक्षण का एकमात्र तरीका इससे जुड़ने की कोशिश कर रहा है।
वाइल्डपलासर

6
यह जवाब मजबूत नहीं है! यदि आपका खोज शब्द किसी अन्य कॉलम में दिखाई देता है तो यह प्रिंट करता है (रिटर्न नहीं!) नॉनज़रो नंबर। कृपया ऐसा करने के लिए अधिक सही तरीके के लिए किबिबू का उत्तर देखें।
अजय

1
"fre-bar" नाम का एक डेटाबेस मौजूद होने पर "grep -w foo" आपको झूठी सकारात्मक जानकारी दे सकता है। नहीं यह उल्लेख करने के लिए psql उत्पादन हेडर में सभी शब्द मिल जाएगा।
मारियस गेदमिनस

1
मैं इस जवाब से पूरी तरह असहमत हूं। यदि आप इस अभिव्यक्ति का तार्किक कथन में उपयोग करते हैं तो यह हमेशा सच होगा। आप इन उदाहरणों का परीक्षण करने की कोशिश कर सकते हैं: psql -l | grep doesnt_matter_what_you_grep | wc -l && echo "true"बनामpsql -l | grep it_does_matter_here && echo "only true if grep returns anything"
माइक लियोन्स

2
सभी काटने के साथ क्या है? यदि आप यह सुनिश्चित करना चाहते हैं कि आप केवल पहले कॉलम को देख रहे हैं, तो बस इसे regex में डालें: psql -l | grep '^ exact_dbname\b'जो यदि मिल जाए तो एक निकास कोड सेट करता है।
स्टीव बेनेट

21

मैं postgresql के लिए नया हूं, लेकिन निम्नलिखित कमांड है जो मैंने जांच की थी कि क्या डेटाबेस मौजूद है

if psql ${DB_NAME} -c '\q' 2>&1; then
   echo "database ${DB_NAME} exists"
fi

9
आगे सरल किया जा सकता है psql ${DB_NAME} -c ''
पेड्रो रोमानो

2
मेरे लिए अच्छा लग रहा है, हालांकि यह गलत हो सकता है अगर डेटाबेस मौजूद है, लेकिन आप इसे कनेक्ट नहीं कर सकते हैं (शायद अनुमति देता है?)
स्टीव बेनेट

7
@SteveBennett, यदि आपके पास आवश्यक DB के लिए कोई अनुमति नहीं है तो यह आपके लिए मौजूद नहीं है :)
Viacheslav Dobysyslov

10

आप एक डेटाबेस बना सकते हैं, अगर यह पहले से मौजूद नहीं है, तो इस विधि का उपयोग करके:

if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi

9

मैं एक संक्षिप्त और POSIX संगत रूप में अन्य उत्तरों को जोड़ रहा हूं:

psql -lqtA | grep -q "^$DB_NAME|"

true(की वापसी )0 ) मतलब है कि यह मौजूद है।

यदि आपको संदेह है कि आपके डेटाबेस के नाम में एक गैर-मानक चरित्र हो सकता है $, जैसे आपको थोड़ा लंबा दृष्टिकोण चाहिए:

psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"

-tऔर -Aविकल्पों के उत्पादन के लिए कच्चे और "सारणीबद्ध" या खाली स्थान के-गद्देदार उत्पादन नहीं है सुनिश्चित करें। स्तंभों को पाइप वर्ण द्वारा अलग किया जाता है |, इसलिए या तो cutयाgrep यह पहचान करने के लिए है। पहले कॉलम में डेटाबेस का नाम है।

संपादित करें: आंशिक नाम मिलान को रोकने के लिए -x के साथ grep।


6
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#

+1 कारण छिटपुट उपयोग के लिए, मैं अन्य उत्तर के लिए विकल्प चुनूंगा, लेकिन एक नियमित स्क्रिप्ट के लिए, यह अधिक स्वच्छ और मजबूत है। कैविएट: जांचें कि उपयोगकर्ता 'पोस्टग्रेज' पासवर्ड के बिना काट सकता है।
leonbloy

हां, उपयोगकर्ता नाम की आवश्यकता के बारे में एक समस्या है। OTOH: आप बिना कनेक्ट की अनुमति के एक अन्य भूमिका का उपयोग नहीं करना चाहेंगे।
21

3

पूर्णता के लिए, स्ट्रिंग काटने के बजाय रेगेक्स का उपयोग करने वाला दूसरा संस्करण:

psql -l | grep '^ exact_dbname\b'

उदाहरण के लिए:

if psql -l | grep '^ mydatabase\b' > /dev/null ; then
  echo "Database exists already."
  exit
fi

उपयोग करने \bमें एक ही समस्या है क्योंकि सभी उत्तरों का उपयोग करके grep -wयह है कि डेटाबेस के नाम में गैर-शब्द-घटक वर्ण जैसे हो सकते हैं -और इसलिए मिलान करने के प्रयास fooभी मेल खाएंगे foo-bar
फिल्स

2

kibibu का स्वीकृत उत्तर त्रुटिपूर्ण है जो किसी भी नाम grep -wसे मेल खाएगा, जिसमें एक शब्द घटक के रूप में निर्दिष्ट पैटर्न है।

यानी यदि आप "फू" खोजते हैं तो "फू-बैकअप" एक मेल है।

ओथियस का जवाब कुछ अच्छे सुधार प्रदान करता है, और लघु संस्करण ज्यादातर मामलों के लिए सही ढंग से काम करेगा, लेकिन लंबे समय तक पेश किए जाने वाले दो वेरिएंट में मेल खाने वाले पदार्थों के साथ एक समान समस्या प्रदर्शित होती है।

इस समस्या को हल करने के लिए, हम POSIX -xतर्क का उपयोग केवल पाठ की संपूर्ण पंक्तियों से मिलान करने के लिए कर सकते हैं ।

ओथियस के जवाब पर बिल्डिंग, नया संस्करण इस तरह दिखता है:

psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"

उस सभी ने कहा, मैं यह कहने के लिए इच्छुक हूं कि निकोलस ग्रिली का जवाब - जहां आप वास्तव में विशिष्ट डेटाबेस के बारे में पोस्टग्रेज पूछते हैं - सभी का सबसे अच्छा तरीका है।


2

अन्य समाधान (जो शानदार हैं) इस तथ्य को याद करते हैं कि psql समय से पहले एक मिनट या उससे अधिक इंतजार कर सकता है यदि वह किसी होस्ट से कनेक्ट नहीं कर सकता है। तो, मैं इस समाधान को पसंद करता हूं, जो टाइमआउट को 3 सेकंड में सेट करता है:

PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""

यह आधिकारिक पर एक विकास डेटाबेस से कनेक्ट करने के लिए है postgres अल्पाइन डोकर छवि।

अलग-अलग, यदि आप रेल का उपयोग कर रहे हैं और एक डेटाबेस सेटअप करना चाहते हैं यदि यह पहले से मौजूद नहीं है (जैसे कि डॉक कंटेनर को लॉन्च करते समय), तो यह अच्छी तरह से काम करता है, क्योंकि माइग्रेशन idempotent हैं:

bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup


0

मैं अभी भी शेल प्रोग्रामिंग के साथ बहुत अनुभवहीन हूं, इसलिए यदि यह वास्तव में किसी कारण से गलत है, तो मुझे वोट दें, लेकिन बहुत चिंतित न हों।

किबिबू के उत्तर से भवन:

# If resulting string is not zero-length (not empty) then...
if [[ ! -z `psql -lqt | cut -d \| -f 1 | grep -w $DB_NAME` ]]; then
  echo "Database $DB_NAME exists."
else
  echo "No existing databases are named $DB_NAME."
fi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.