ฉันสงสัยว่าจะมีใครบอกฉันได้บ้างว่าสามารถใช้เชลล์เพื่อตรวจสอบฐานข้อมูล PostgreSQL ได้หรือไม่?
ฉันกำลังสร้างเชลล์สคริปต์และฉันต้องการให้สร้างฐานข้อมูลหากยังไม่มีอยู่ แต่จนถึงตอนนี้ยังไม่สามารถดูวิธีใช้งานได้
ฉันสงสัยว่าจะมีใครบอกฉันได้บ้างว่าสามารถใช้เชลล์เพื่อตรวจสอบฐานข้อมูล PostgreSQL ได้หรือไม่?
ฉันกำลังสร้างเชลล์สคริปต์และฉันต้องการให้สร้างฐานข้อมูลหากยังไม่มีอยู่ แต่จนถึงตอนนี้ยังไม่สามารถดูวิธีใช้งานได้
คำตอบ:
ฉันใช้การปรับเปลี่ยนโซลูชันของ 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
ตรงกับตัวอักษรและตัวเลขตัวเลขและขีดล่างซึ่งตรงกับชุดของอักขระที่อนุญาตในชื่อฐานข้อมูลที่ไม่ได้ใส่เครื่องหมายใน postgresql (ขีดกลางไม่ถูกต้องตามกฎหมายในตัวระบุที่ไม่ได้ใส่เครื่องหมายอัญประกาศ) หากคุณใช้อักขระอื่น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
wc
ทั้งหมด ดูการแก้ไขของฉัน (ถ้าคุณต้องการที่จะกลับออกจากสถานะการทุบตีสนับสนุนผู้ประกอบการปัง: ! psql ...
)
wc
คำสั่งฉันจะใช้grep -qw <term>
. สิ่งนี้จะทำให้เชลล์กลับมา0
หากมีการจับคู่หรือ1
อย่างอื่น จากนั้น$?
จะมีมูลค่าส่งคืนและคุณสามารถใช้เพื่อตัดสินใจว่าจะทำอะไรต่อไป ดังนั้นฉันไม่แนะนำให้ใช้wc
ในกรณีนี้ grep
จะทำในสิ่งที่คุณต้องการ
ดูเหมือนว่ารหัสเชลล์ต่อไปนี้จะใช้ได้กับฉัน:
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
psql -U user -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" template1
if [[ $(...) == 1* ]]
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
สิ่งนี้จะส่งคืน 1 หากฐานข้อมูลที่ระบุมีอยู่หรือ 0 มิฉะนั้น
นอกจากนี้หากคุณพยายามสร้างฐานข้อมูลที่มีอยู่แล้ว postgresql จะส่งคืนข้อความแสดงข้อผิดพลาดดังนี้:
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
exact_dbname_test
? วิธีเดียวในการทดสอบคือพยายามเชื่อมต่อกับมัน
psql -l | grep doesnt_matter_what_you_grep | wc -l && echo "true"
vspsql -l | grep it_does_matter_here && echo "only true if grep returns anything"
psql -l | grep '^ exact_dbname\b'
ซึ่งจะตั้งค่ารหัสออกหากไม่พบ
ฉันเพิ่งเริ่มใช้ postgresql แต่คำสั่งต่อไปนี้คือสิ่งที่ฉันใช้เพื่อตรวจสอบว่ามีฐานข้อมูลอยู่หรือไม่
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
psql ${DB_NAME} -c ''
อีก
คุณสามารถสร้างฐานข้อมูลได้หากยังไม่มีโดยใช้วิธีนี้:
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
ฉันกำลังรวมคำตอบอื่น ๆ เข้ากับแบบฟอร์มที่กระชับและเข้ากันได้กับ POSIX:
psql -lqtA | grep -q "^$DB_NAME|"
การกลับมาของtrue
( 0
) หมายความว่ามีอยู่จริง
หากคุณสงสัยว่าชื่อฐานข้อมูลของคุณอาจมีอักขระที่ไม่เป็นมาตรฐานเช่น$
คุณต้องใช้แนวทางที่ยาวกว่านี้เล็กน้อย:
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
-t
และ-A
ตัวเลือกให้แน่ใจว่าการส่งออกเป็นวัตถุดิบและไม่ "ตาราง" หรือช่องว่างเบาะเอาท์พุท คอลัมน์จะถูกคั่นด้วยอักขระไปป์|
ดังนั้นcut
หรือgrep
ต้องรู้จักสิ่งนี้ คอลัมน์แรกประกอบด้วยชื่อฐานข้อมูล
แก้ไข: grep ด้วย -x เพื่อป้องกันการจับคู่ชื่อบางส่วน
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
เพื่อความสมบูรณ์เวอร์ชันอื่นที่ใช้ regex แทนการตัดสตริง:
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
ด้วย
คำตอบที่ยอมรับของ kibibu มีข้อบกพร่องgrep -w
ตรงที่จะจับคู่ชื่อใด ๆที่มีรูปแบบที่ระบุเป็นส่วนประกอบของคำ
เช่นถ้าคุณมองหา "foo" แล้ว "foo-backup" จะตรงกัน
คำตอบของ Otheusมีการปรับปรุงที่ดีและเวอร์ชันสั้น ๆ จะทำงานได้อย่างถูกต้องสำหรับกรณีส่วนใหญ่ แต่ตัวแปรทั้งสองที่มีความยาวกว่าจะแสดงปัญหาที่คล้ายกันกับสตริงย่อยที่ตรงกัน
ในการแก้ไขปัญหานี้เราสามารถใช้-x
อาร์กิวเมนต์POSIX เพื่อจับคู่ข้อความทั้งบรรทัดเท่านั้น
จากคำตอบของ Otheus เวอร์ชันใหม่จะมีลักษณะดังนี้:
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
ทั้งหมดที่กล่าวมาฉันมีแนวโน้มที่จะบอกว่าคำตอบของ Nicolas Grillyซึ่งเป็นที่ที่คุณถาม postgres เกี่ยวกับฐานข้อมูลเฉพาะนั้นเป็นแนวทางที่ดีที่สุด
วิธีแก้ปัญหาอื่น ๆ (ซึ่งยอดเยี่ยมมาก) พลาดข้อเท็จจริงที่ว่า psql สามารถรอหนึ่งนาทีหรือมากกว่านั้นก่อนที่จะหมดเวลาหากไม่สามารถเชื่อมต่อกับโฮสต์ได้ ฉันชอบโซลูชันนี้ซึ่งตั้งค่าการหมดเวลาเป็น 3 วินาที:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
ใช้สำหรับเชื่อมต่อกับฐานข้อมูลการพัฒนาบนภาพpostgres Alpine Docker อย่างเป็นทางการ
แยกกันหากคุณใช้ Rails และต้องการตั้งค่าฐานข้อมูลหากยังไม่มีอยู่ (เช่นเมื่อเปิดใช้งานคอนเทนเนอร์ Docker) สิ่งนี้จะทำงานได้ดีเนื่องจากการย้ายข้อมูลเป็นสิ่งที่ไม่จำเป็น:
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
psql -l|awk '{print $1}'|grep -w <database>
รุ่นที่สั้นกว่า
ฉันยังไม่ค่อยมีประสบการณ์กับการเขียนโปรแกรมเชลล์ดังนั้นหากสิ่งนี้ผิดพลาดจริงๆด้วยเหตุผลบางประการให้โหวตฉันลง แต่อย่าตื่นตระหนกเกินไป
สร้างจากคำตอบของ kibibu:
# 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
... | grep 0
เพื่อให้ค่าส่งคืนเชลล์เป็น 0 หากไม่มี DB และ 1 ถ้าเป็นเช่นนั้น หรือ... | grep 1
พฤติกรรมตรงกันข้าม