Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม BASH

วิธีใช้สคริปต์ทุบตีเพื่อจัดการการดาวน์โหลดและการดูไฟล์จากบัคเก็ต AWS S3

ตามที่คุณสามารถอ่านได้ในบทความนี้ เมื่อเร็วๆ นี้ ฉันมีปัญหากับเซิร์ฟเวอร์อีเมลของฉัน และตัดสินใจจ้างการจัดการอีเมลจากภายนอกไปยัง Simple Email Service (SES) ของ Amazon

ปัญหาของวิธีแก้ปัญหาคือฉันมี SES บันทึกข้อความใหม่ไปยังบัคเก็ต S3 และการใช้ AWS Management Console เพื่ออ่านไฟล์ภายในบัคเก็ต S3 นั้นค้างเร็วมาก

ดังนั้นฉันจึงตัดสินใจเขียนสคริปต์ทุบตีเพื่อทำให้กระบวนการดาวน์โหลด จัดเก็บอย่างถูกต้อง และดูข้อความใหม่เป็นไปโดยอัตโนมัติ

ในขณะที่ฉันเขียนสคริปต์นี้เพื่อใช้บนเดสก์ท็อป Ubuntu Linux ก็ไม่ต้องเล่นซอมากเกินไปเพื่อให้ทำงานบนระบบ macOS หรือ Windows 10 ผ่าน Windows SubSystem for Linux

นี่คือสคริปต์ที่สมบูรณ์ทั้งหมดในชิ้นเดียว หลังจากที่คุณใช้เวลาสักครู่เพื่อดูมัน เราจะแนะนำคุณทีละขั้นตอน

#!/bin/bash
# Retrieve new messages from S3 and save to tmpemails/ directory:
aws s3 cp \
   --recursive \
   s3://bucket-name/ \
   /home/david/s3-emails/tmpemails/  \
   --profile myaccount

# Set location variables:
tmp_file_location=/home/david/s3-emails/tmpemails/*
base_location=/home/david/s3-emails/emails/

# Create new directory to store today's messages:
today=$(date +"%m_%d_%Y")
[[ -d ${base_location}/"$today" ]] || mkdir ${base_location}/"$today"

# Give the message files readable names:
for FILE in $tmp_file_location
do
   mv $FILE ${base_location}/${today}/email$(rand)
done

# Open new files in Gedit:
for NEWFILE in ${base_location}/${today}/*
do
   gedit $NEWFILE
done

เราจะเริ่มต้นด้วยคำสั่งเดียวเพื่อดาวน์โหลดข้อความใดๆ ที่อยู่ในบัคเก็ต S3 ของฉัน (อย่างไรก็ตาม ฉันได้เปลี่ยนชื่อของบัคเก็ตและระบบไฟล์อื่นๆ และรายละเอียดการตรวจสอบสิทธิ์เพื่อปกป้องความเป็นส่วนตัวของฉัน)

aws s3 cp \
   --recursive \
   s3://bucket-name/ \
   /home/david/s3-emails/tmpemails/  \
   --profile myaccount

แน่นอนว่าวิธีนี้จะได้ผลก็ต่อเมื่อคุณได้ติดตั้งและกำหนดค่า AWS CLI สำหรับระบบในพื้นที่ของคุณแล้ว ถึงเวลาทำสิ่งนี้แล้ว หากคุณยังไม่ได้ทำ

cp คำสั่งย่อมาจาก "copy" --recursive บอกให้ CLI ใช้การดำเนินการกับหลายวัตถุ s3://bucket-name ชี้ไปที่ที่ฝากข้อมูลของฉัน (ชื่อถังของคุณจะแตกต่างกันอย่างชัดเจน) บรรทัด /home/david... คือที่อยู่ระบบไฟล์ที่แน่นอนซึ่งฉันต้องการคัดลอกข้อความ และ --profile อาร์กิวเมนต์บอก CLI ว่าฉันกำลังอ้างถึงบัญชี AWS ใดของฉัน

ส่วนถัดไปตั้งค่าตัวแปรสองตัวที่จะช่วยให้ระบุตำแหน่งระบบไฟล์ได้ง่ายขึ้นมากในส่วนที่เหลือของสคริปต์

tmp_file_location=/home/david/s3-emails/tmpemails/*
base_location=/home/david/s3-emails/emails/

สังเกตว่าค่าของ tmp_file_location ตัวแปรลงท้ายด้วยเครื่องหมายดอกจัน นั่นเป็นเพราะฉันต้องการอ้างถึง ไฟล์ภายใน ไดเร็กทอรีนั้น แทนที่จะเป็นไดเร็กทอรีเอง

ฉันจะสร้างไดเร็กทอรีถาวรใหม่ภายใน .../emails/ ลำดับชั้นเพื่อให้ค้นหาข้อความได้ง่ายขึ้นในภายหลัง ชื่อของไดเร็กทอรีใหม่นี้จะเป็นวันที่ปัจจุบัน

today=$(date +"%m_%d_%Y")
[[ -d ${base_location}/"$today" ]] || mkdir ${base_location}/"$today"

ก่อนอื่นฉันสร้างตัวแปรเชลล์ใหม่ชื่อ วันนี้ ที่จะถูกเติมโดยเอาต์พุตของ date +"%m_%d_%Y" สั่งการ. วันที่ ตัวเองแสดงวันที่/เวลาเต็ม แต่สิ่งที่ตามมา ("%m_%d_%Y" ) แก้ไขผลลัพธ์ให้อยู่ในรูปแบบที่เรียบง่ายและอ่านง่ายขึ้น

จากนั้นฉันก็ทดสอบการมีอยู่ของชื่อนั้นโดยตรง ซึ่งแสดงว่าฉันได้รับอีเมลแล้วในวันนั้น ดังนั้นจึงไม่จำเป็นต้องสร้างไดเรกทอรีขึ้นใหม่ หากไดเรกทอรีดังกล่าว ไม่ มีอยู่ (||) จากนั้น mkdir จะสร้างมันให้ฉัน หากคุณไม่ทำการทดสอบนี้ คำสั่งของคุณอาจส่งคืนข้อความแสดงข้อผิดพลาดที่น่ารำคาญ

เนื่องจาก Amazon SES ให้ชื่อที่น่าเกลียดและอ่านไม่ได้แก่แต่ละข้อความที่ส่งไปยังบัคเก็ต S3 ของฉัน ตอนนี้ฉันจะเปลี่ยนชื่อแบบไดนามิกในขณะที่ย้ายไปยังบ้านใหม่ (ในไดเร็กทอรีเก่าที่ฉันเพิ่งสร้างขึ้น) .

for FILE in $tmp_file_location
do
   mv $FILE ${base_location}/${today}/email$(rand)
done

สำหรับ...ทำ...เสร็จแล้ว loop จะอ่านแต่ละไฟล์ในไดเร็กทอรีที่แสดงโดย $tmp_file_location จากนั้นย้ายไปยังไดเร็กทอรีที่ฉันเพิ่งสร้าง (แสดงโดย $base_location ตัวแปรนอกเหนือจากค่าปัจจุบันของ $วันนี้ ).

ในการดำเนินการเดียวกันนี้ ฉันจะตั้งชื่อใหม่ให้กับมัน สตริง "อีเมล " ตามด้วยตัวเลขสุ่มที่สร้างโดย แรนด์ สั่งการ. คุณอาจต้องติดตั้งตัวสร้างตัวเลขสุ่ม นั่นคือ apt install rand บนอูบุนตู

เวอร์ชันก่อนหน้าของสคริปต์สร้างชื่อโดยแยกความแตกต่างด้วยตัวเลขที่สั้นกว่าและเรียงตามลำดับซึ่งเพิ่มขึ้นโดยใช้ count=1...count=$((count+1)) ตรรกะภายใน สำหรับ ห่วง ใช้งานได้ดีตราบใดที่ฉันไม่ได้รับข้อความมากกว่าหนึ่งชุดในวันเดียวกัน ถ้าฉันทำ ข้อความใหม่จะเขียนทับไฟล์เก่าในไดเร็กทอรีของวันนั้น

ฉันเดาว่าเป็นไปได้ในทางคณิตศาสตร์ที่ rand . ของฉัน คำสั่งสามารถกำหนดหมายเลขที่ทับซ้อนกันให้กับไฟล์สองไฟล์ แต่เนื่องจากช่วงเริ่มต้น rand การใช้งานอยู่ระหว่าง 1 ถึง 32,576 นั่นคือความเสี่ยงที่ฉันยินดีรับ

ณ จุดนี้ ควรมีไฟล์ในไดเร็กทอรีใหม่ที่มีชื่อเช่น email3039, email25343 เป็นต้น สำหรับแต่ละข้อความใหม่ที่ฉันส่งไป

วิ่ง ต้นไม้ คำสั่งในระบบของฉันแสดงให้ฉันเห็นว่าข้อความห้าข้อความถูกบันทึกไว้ในไดเร็กทอรี 02_27_2020 ของฉัน และอีกหนึ่งข้อความใน 02_28_2020 (ไฟล์เหล่านี้สร้างขึ้นโดยใช้สคริปต์เวอร์ชันเก่าของฉัน ดังนั้นพวกมันจึงถูกเรียงลำดับตามลำดับ)

ขณะนี้ไม่มีไฟล์ใน tmpemails - นั่นเป็นเพราะคำสั่ง mv จะย้ายไฟล์ไปยังตำแหน่งใหม่โดยไม่ทิ้งอะไรไว้

$ tree
.
├── emails
│   ├── 02_27_2020
│   │   ├── email1
│   │   ├── email2
│   │   ├── email3
│   │   ├── email4
│   │   ├── email5
│   └── 02_28_2020
│       └── email1
└── tmpemails

ส่วนสุดท้ายของสคริปต์จะเปิดแต่ละข้อความใหม่ในโปรแกรมแก้ไขข้อความบนเดสก์ท็อปที่ฉันโปรดปราน (Gedit) ใช้ for...do...done . ที่คล้ายกัน วนซ้ำ คราวนี้อ่านชื่อของแต่ละไฟล์ในไดเร็กทอรีใหม่ (อ้างอิงโดยใช้ "วันนี้ " คำสั่ง) จากนั้นเปิดไฟล์ใน Gedit สังเกตเครื่องหมายดอกจันที่ฉันเพิ่มไว้ที่ส่วนท้ายของตำแหน่งไดเรกทอรี

for NEWFILE in ${base_location}/${today}/*
do
   gedit $NEWFILE
done

ยังมีอีกสิ่งหนึ่งที่ต้องทำ หากฉันไม่ล้างบัคเก็ต S3 ออก ระบบจะดาวน์โหลดข้อความสะสมทั้งหมดทุกครั้งที่ฉันเรียกใช้สคริปต์ นั่นจะทำให้การจัดการยากขึ้นเรื่อย ๆ

ดังนั้น หลังจากดาวน์โหลดข้อความใหม่สำเร็จแล้ว ฉันจึงเรียกใช้สคริปต์สั้นๆ นี้เพื่อลบไฟล์ทั้งหมดในที่เก็บข้อมูล:

#!/bin/bash
# Delete all existing emails 

aws s3 rm --recursive s3://bucket-name/ --profile myaccount