لماذا لا نجعل عملية النسخ الاحتياطي بسيطة قدر الإمكان؟ أعني باستخدام أمر واحد ، يتم نسخ محتويات الموقع وقاعدة البيانات احتياطيًا عن بُعد ومحليًا. دعونا نرى كيف يمكننا تحقيق ذلك الأمر.
المقدمة:

إذا فكرنا في الأمر ، فسنعلم أننا بحاجة إلى ملفين / نصوص. يجب أن يبقى أحدهم في خادم الموقع (عن بعد) مع وظيفة واحدة ، وهي رعاية عملية النسخ الاحتياطي. بينما يجب أن يكون البرنامج النصي الآخر على جهاز الكمبيوتر الخاص بنا (محليًا) ، والذي يحتوي على وظيفتين. الأول ، هو إخبار البرنامج النصي البعيد ببدء عملية النسخ الاحتياطي. والمهمة الثانية هي تنزيل النسخ الاحتياطية إلى جهاز الكمبيوتر الخاص بنا بمجرد اكتمالها.
نرغب أيضًا في تنظيم النسخ الاحتياطية الخاصة بنا عن طريق تخزينها في مجلدات فرعية تسمى بتاريخ حدوث النسخ الاحتياطي. قد نرغب أيضًا في الاحتفاظ بنسخة من هذه النسخة الاحتياطية على خادم موقعنا كنسخة ثانية. لذا فإن الهدف هو تحقيق كل ذلك من خلال تنفيذ أمر واحد بسيط. يبدو مثيراً؟ رائع ، دعنا نرى كيف نفعل ذلك.
مستودع GitLab:
يمكن العثور عليها في unix.cafe/website-backup. أو استنساخه عن طريق تنفيذ ما يلي في سطر الأوامر:
git clone https://gitlab.com/unix.cafe/website-backup.git
على الجانب البعيد (خادم الموقع):
المتطلبات:
تثبيت المتطلبات:
- على Debian ومشتقاته: (مثل: Ubuntu / Linux Mint / Devuan / elementary OS / MX Linux / antiX / deepin / Linux Lite / Zorin OS / LXLE / Peppermint OS / SparkyLinux):
apt install openssh-server rsync. - على Fedora / RedHat 8+ / CentOS 8+ / Scientific Linux 8+:
dnf install openssh-server rsync. - على RedHat 7 / CentOS 7 / Scientific Linux 7:
yum install openssh-server rsync. - على Mageia:
urpmi openssh-server rsync. - على ArchLinux ومشتقاته: (مثل: Manjaro / KaOS / ArchBang Linux / BlackArch Linux / Parabola GNU/Linux-libre / Chakra GNU/Linux):
pacman -S openssh rsync. - على SUSE / OpenSUSE:
zypper in openssh rsync. - على Gentoo:
emerge net-misc/openssh net-misc/rsync. - على Void Linux:
xbps-install -S openssh rsync. - على Alpine:
apk add openssh-client rsync. - على FreeBSD:
pkg install rsync. (OpenSSH مثبت تلقائياً). - على MacOSX: يتم شحن جميع الحزم المطلوبة بالفعل مع نظام التشغيل. ولكن إذا احتجت إلى تثبيتها عبر MacPorts لسبب ما ، اكتب:
port install openssh rsync.
تمكين وبدء خدمة SSH:
- على SystemD توزيعات Linux: لتمكين وبدء نوع خدمة SSH:
systemctl enable --now sshd. - على OpenRC توزيعات Linux: لتمكين نوع خدمة SSH:
rc-update add sshd, وللبدء اكتب:service sshd start. - على FreeBSD: لتمكين نوع خدمة SSH:
sysrc sshd_enable=YES, وللبدء اكتب:service sshd start. - على MacOSX: لتمكين تسجيل دخول SSH من الاتصالات البعيدة ، اكتب:
systemsetup -setremotelogin on. - إذا كنت تستخدم مدير خدمات آخر ، فألق نظرة على: كيفية: إدارة الخدمة في systemd و SysVinit و Upstart و runit و OpenRC
التحضير للبرنامج النصي للنسخ الاحتياطي لدينا:
أولاً ، نحتاج إلى إنشاء ملف برنامج نصي احتياطي. الأمر متروك لك لتسمية ما تريد ، وتخزينه أينما تريد. ولكن من فضلك لا تخزن داخل مجلد الجذر لخادم الويب الخاص بك (والذي عادة ما يسمى public_html) حتى لا يتمكن أي شخص آخر غيرك من الوصول إليه. في هذا المثال سأقوم بتسميته bkp وسأضعه في ~/bin/. لذلك مسارها الكامل هو ~/bin/bkp. لنفعل ذلك:
لنقم بإنشاء المجلد ~/bin:
[deadsoul@remote ~]$ mkdir ~/bin
الآن ، دعنا ننشئ الملف bkp:
[deadsoul@remote ~]$ touch ~/bin/bkp
الآن ، دعونا نجعل ~/bin/bkp قابل للتنفيذ من قبلنا كمالكها:
[deadsoul@remote ~]$ chmod u+x ~/bin/bkp
البرنامج النصي للنسخ الاحتياطي (رمز المصدر):
رائع ، الآن دعنا ننسخ المصدر التالي ونلصقه داخل ~/bin/bkp. يمكنك استخدام nano أو vim أو Kate أو أي محرر تريده.
#!/bin/bash
# configuration
DSTDIR="/path/to/where/to/store/backups"
SRCDIR="/path/to/what/to/backup"
DBNAME='db-name'
DBUSER='db-user'
DBPASS='db-pass'
# ------------------------------------------------------------------------------------------
# You don't have to modify anything else below this line, unless you know what you're doing
# ------------------------------------------------------------------------------------------
# prepare sub-directory name
DATE=$(date +'%Y%m%d')
TIME=$(date +'%H%M%S')
SUBDIR="${DSTDIR}/${DATE}"
DIRNAME=$(basename "$SRCDIR")
# create the sub-directory
[[ -e "${SUBDIR}" ]] && SUBDIR="${SUBDIR}-${TIME}"
mkdir -p "${SUBDIR}"
# backing up files
echo -e '\n * Backing up files …'; sleep 2
tar -zcpf "${SUBDIR}/${DIRNAME}.tar.gz" "$SRCDIR"
# backing up db
echo -e '\n * Backing up database …\n'; sleep 2
mysqldump ${DBNAME} -u ${DBUSER} -p${DBPASS} > "${DBNAME}.sql"
tar -zcpf "${SUBDIR}/${DBNAME}.sql.tar.gz" "${DBNAME}.sql"
rm -f "${DBNAME}.sql"ماذا تفعل؟ (شرح):
# configuration DSTDIR="/path/to/where/to/store/backups" SRCDIR="/path/to/what/to/backup" DBNAME='db-name' DBUSER='db-user' DBPASS='db-pass'
DSTDIR: هو متغير يحمل مكان تخزين جميع النسخ الاحتياطية. (بدون شرطة مائلة لاحقة (/))SRCDIR: هو متغير يحمل موقع المجلد الذي يجب نسخه احتياطيًا. (بدون شرطة مائلة)DBNAME: هو متغير يحمل اسم قاعدة البيانات.DBUSER: هو متغير يحمل مستخدم قاعدة البيانات.DBPASS: هو متغير يحمل كلمة مرور قاعدة البيانات.
# prepare sub-directory name
DATE=$(date +'%Y%m%d')
TIME=$(date +'%H%M%S')
SUBDIR="${DSTDIR}/${DATE}"
DIRNAME=$(basename "$SRCDIR")DATE: هو متغير يحمل التاريخ الحالي السنةالشهراليوم (YearMonthDay). (على سبيل المثال: 20200603)TIME: متغير يحمل الوقت الساعةالدقيقةالثانية (HourMinuteSecond) الحالي. (على سبيل المثال: 193520)SUBDIR: هو متغير يحمل قيمة$DSTDIRمتبوعًا ب/متبوعًا بقيمة$DATE.DIRNAME: هو متغير يحمل اسم المجلد الذي نريد نسخه احتياطيًا. وهوpublic_htmlفي مثالنا.
# create the sub-directory
[[ -e "${SUBDIR}" ]] && SUBDIR="${SUBDIR}-${TIME}"
mkdir -p "${SUBDIR}"[[ -e "${SUBDIR}" ]] && SUBDIR="${SUBDIR}-${TIME}"يتحقق من وجود اسم المجلد الفرعي الذي تم إنشاؤه ($SUBDIR). إذا كان موجودًا ، فإننا نطلب منه إلحاق شرطة-وقيمة$TIMEلاسم المجلد الفرعي الذي تم إنشاؤه ، لنجعله فريدًا.- بعد ذلك نقوم بإنشاء هذا المجلد بالأمر
mkdir -p "${SUBDIR}". (استخدمنا الخيار-pأيضًا لإنشاء أي مجلد في مسار$SUBDIRغير موجود. وهو أمر مفيد في حالة استخدام البرنامج النصي للمرة الأولى ونسينا إنشاء$DSTDIR).
# backing up files
echo -e '\n * Backing up files …'; sleep 2
tar -zcpf "${SUBDIR}/${DIRNAME}.tar.gz" "$SRCDIR"echo -e '\n * Backing up files …';نحن نطبع ما نحن على وشك القيام به. وsleep 2يعني الانتظار لمدة ثانيتين قبل القفز إلى عبارة BASH التالية.tar -zcpf "${SUBDIR}/${DIRNAME}.tar.gz" "$SRCDIR"نحن ننشئ كرة مضغوطة منpublic_htmlوملكيتها وأذوناتها.
# backing up db
echo -e '\n * Backing up database …\n'; sleep 2
mysqldump ${DBNAME} -u ${DBUSER} -p${DBPASS} > "${DBNAME}.sql"
tar -zcpf "${SUBDIR}/${DBNAME}.sql.tar.gz" "${DBNAME}.sql"
rm -f "${DBNAME}.sql"echo -e '\n * Backing up database …\n';مرة أخرى ، نحن نطبع ما نحن على وشك القيام به. وsleep 2يعني الانتظار لمدة ثانيتين قبل القفز إلى عبارة BASH التالية.mysqldump ${DBNAME} -u ${DBUSER} -p${DBPASS} > "${DBNAME}.sql"نقوم بإفراغ قاعدة البيانات في ملف يسمى بقيمة$DBNAMEمتبوعة بـ.sql.tar -zcpf "${SUBDIR}/${DBNAME}.sql.tar.gz" "${DBNAME}.sql"ثم نقوم بضغط هذا الملف الذي تم تفريغه.rm -f "${DBNAME}.sql"أخيرًا ، نزيل ملف SQL هذا. لأن لدينا نسخة مضغوطة منه.
ترتيب:
حان الوقت لتعديل بعض الخطوط فيه. (من السطر رقم 4 إلى السطر رقم 8). وفقًا لإعداداتك ، اضبط القيم التالية:
DSTDIR="/path/to/where/to/store/backups" SRCDIR='/path/to/what/to/backup' DBNAME='db-name' DBUSER='db-user' DBPASS='db-pass'
في هذا المثال سنفترض أن المجلد المطلوب لتخزين النسخ الاحتياطية المأخوذة هو ~/backups ، والمجلد الذي نريد نسخه احتياطيًا هو ~/public_html ، ثم سنقوم بتعديله على النحو التالي
DSTDIR="$HOME/backups" SRCDIR="$HOME/public_html"
لنفترض أن بيانات اعتماد قاعدة البيانات الخاصة بنا على النحو التالي:
DBNAME='wp_blog' DBUSER='deadsoul' DBPASS='password'
وهذا هو الجانب البعيد (خادم الموقع). دعونا نرى الآن ما يجب القيام به على الجانب المحلي (جهاز الكمبيوتر الخاص بنا).
على الجانب المحلي (جهاز الكمبيوتر الخاص بك):
المتطلبات:
- SSH: مطلوب للتواصل بشكل آمن مع خادم الموقع.
- Rsync: نحتاجة لنقل النسخ الاحتياطية إلى الجهاز المحلي.
- Expect (اختياري. فقط إذا لم يكن لديك مفتاح ssh بدون كلمة مرور ، أو إذا كنت تمانع في إدخال كلمة المرور أكثر من مرة لكل نسخة احتياطية)
التثبيت:
- على Debian ومشتقاته: (مثل: Ubuntu / LinuxMint / Devuan / elementary OS / MX Linux / deepin / Linux Lite / Zorin OS / LXLE / Peppermint OS / SparkyLinux):
apt install openssh-client rsync expect. - على Fedora / RedHat 8+ / CentOS 8+ / Scientific Linux 8+:
dnf install openssh-clients rsync expect. - على RedHat 7 / CentOS 7 / Scientific Linux 7:
yum install openssh-clients rsync expect. - على Mageia:
urpmi openssh-clients rsync expect. - على ArchLinux ومشتقاته: (مثل: Manjaro / KaOS / ArchBang Linux / BlackArch Linux / Parabola GNU/Linux-libre / Chakra GNU/Linux):
pacman -S openssh rsync expect. - على SUSE / OpenSUSE:
zypper in openssh rsync expect. - على Gentoo:
emerge net-misc/openssh net-misc/rsync dev-tcltk/expect. - على VoidLinux:
xbps-install -S openssh rsync expect. - على Alpine:
apk add openssh-client rsync expect. - على FreeBSD:
pkg install rsync expect. (OpenSSH is installed by default). - على MacOSX: يتم شحن جميع الحزم المطلوبة بالفعل مع نظام التشغيل. ولكن إذا احتجت إلى تثبيتها عبر MacPorts لسبب ما ، اكتب
port install openssh rsync expect.
التحضير للبرنامج النصي النسخ الاحتياطي لدينا:
ولاً ، نحتاج إلى إنشاء ملف برنامج نصي احتياطي. الأمر متروك لك لتسمية ما تريد ، وتخزينه أينما تريد. في هذا المثال سأقوم بتسميته bkp وسأضعه في ~/bin/. لذلك مسارها الكامل هو ~/bin/bkp. لنفعل ذلك:
لنصنع المجلد ~/bin:
[deadsoul@local ~]$ mkdir ~/bin
الآن, لنصنع ملف الــ bkp:
[deadsoul@local ~]$ touch ~/bin/bkp
الآن ، دعونا نجعل ~/bin/bkp قابل للتنفيذ (executable) من قبلنا كمالكها:
[deadsoul@local ~]$ chmod u+x ~/bin/bkp
دعونا نتأكد من أن هذا الموقع ~/bin موجود في المتغير $PATH. بتحرير ~/.bashrc ، وإضافة ما يلي إلى النهاية:
if ! [[ "$PATH" =~ "$HOME/bin" ]]; then
PATH="$HOME/bin:$PATH"
export PATH
fiثم فقط قم بحفظ الملف والخروج. إذا قمت بالتحرير عن طريق المحطة الطرفية ، فاكتب source ~/.bashrc لتطبيق التغييرات.
ملاحظات البرنامج النصي للنسخ الاحتياطي:
- إذا كنت تستخدم SSH إلى الخادم الخاص بك بكلمة مرور أو عبارة مرور رئيسية ولا تريد إدخال كلمة المرور الخاصة بك أكثر من مرة ، فاستخدم
Expectversion. عن طريق نسخ محتواه إلى ملفbkp. - إذا كنت لا تمانع في إدخال كلمة المرور الخاصة بك أكثر من مرة ، أو إذا كنت تستخدم مفتاحًا بدون كلمة مرور ، فاستخدم version
BASH. عن طريق نسخ محتواه إلى ملفbkp.
البرنامج النصي النسخ الاحتياطي (Expect version):
#!/usr/bin/expect
set timeout -1
# grab the password
stty -echo
puts " "
send_user -- "Enter your ssh password: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set SSHPASS $expect_out(1,string)
# configuration
set SRV_USER your_username
set SRV_HOST your_server_host
set SRV_BKP_SCRIPT path_to_bkp_on_server
set SRV_BACKUPS_DIR path_to_backups_on_server_with_trailing_slash
set LOCAL_ARCHIVE_DIR path_to_local_archive_with_trailing_slash
# ask bkp on server to take a backup
puts " "
puts "Connecting to website.."
spawn ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT"
expect {
"Enter passphrase for key" { send -- "$SSHPASS\r" }
"password" { send -- "$SSHPASS\r" }
}
interact
# download the taken backup
puts " "
puts "Downloading the backups.."
spawn rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR"
expect {
"Enter passphrase for key" { send -- "$SSHPASS\r" }
"password" { send -- "$SSHPASS\r" }
}
interactماذا تفعل؟ (تفسير):
set timeout -1 # grab the password stty -echo puts " " send_user -- "Enter your ssh password: " expect_user -re "(.*)\n" send_user "\n" stty echo set SSHPASS $expect_out(1,string)
set timeout -1: تعطيل المهلة من البرنامج النصيexpectالخاص بنا.stty -echo: تعطيل صدى المدخلات من سطر الأوامر.puts " ": طباعة سطر فارغ.send_user -- "Enter your ssh password: ": يطبع موجه كلمة المرور.expect_user -re "(.*)\n": يقرأ مدخلاتنا.send_user "\n": طباعة خط جديد.stty echo: إعادة تمكين صدى المدخلات من سطر الأوامر.set SSHPASS $expect_out(1,string): يعين كلمة المرور المدخلة للمتغيرSSHPASS.
# configuration set SRV_USER your_username set SRV_HOST your_server_host set SRV_BKP_SCRIPT path_to_bkp_on_server set SRV_BACKUPS_DIR path_to_backups_on_server_with_trailing_slash set LOCAL_ARCHIVE_DIR path_to_local_archive_with_trailing_slash
SRV_USER: هو متغير يحمل مستخدم الــ SSH البعيد.SRV_HOST: هو متغير يحمل مضيف SSH البعيد.SRV_BKP_SCRIPT: هو متغير يحمل المسار إلى البرنامج النصيbkpفي الجانب الخادمي.SRV_BACKUPS_DIR: هو متغير يحمل مسار النسخ الاحتياطي المخزن في جانب الخادم ، ويجب أن يكون مطابقًا لقيمة$DSTDIRالموجودة في نصbkpالموجود في جانب الخادم. (مع شرطة مائلة)LOCAL_ARCHIVE_DIR: هو متغير يحمل المسار لمجلد محلي نود استخدامه لتخزين جميع النسخ الاحتياطية المأخوذة عن بعد. (مع شرطة مائلة)
# ask bkp on server to take a backup
puts " "
puts "Connecting to website.."
spawn ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT"
expect {
"Enter passphrase for key" { send -- "$SSHPASS\r" }
"password" { send -- "$SSHPASS\r" }
}
interactputs " ": طباعة سطر فارغ.puts "Connecting to website..": طباعة رسالة التوصيل.spawn ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT": تنفيذ البرنامج النصيbkpعلى جانب الخادم عبر ssh.expect {: يعالج المواقف المحددة مسبقًا بينexpect {… و …}."Enter passphrase for key" { send -- "$SSHPASS\r" }: إذا كان الخادم يستجيب لنا بشيء يحتوي علىإدخال عبارة مرور للمفتاح، فإننا نرد بقيمة$SSHPASSمتبوعة بـ enter."password" { send -- "$SSHPASS\r" }: مرة أخرى ، إذا كان الخادم يستجيب لنا بشيء يحتوي علىكلمة مرور، فإننا نرد بقيمة$SSHPASSمتبوعة بإدخال.interact: يتفاعل مع العملية.
# download the taken backup
puts " "
puts "Downloading the backups.."
spawn rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR"
expect {
"Enter passphrase for key" { send -- "$SSHPASS\r" }
"password" { send -- "$SSHPASS\r" }
}
interactspawn rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR": تنفيذ الأمرrsyncلتنزيل كافة النُسَخ الاحتياطية الموجودة.- تم شرح باقي الخطوط أعلاه.
ترتيب:
حان الوقت لتكوينه. (من السطر رقم 15 إلى السطر رقم 19). وفقًا لإعداداتك ، اضبط القيم التالية:
- سنفترض أن اسم المستخدم لدينا هو
deadsoulوأن مضيف موقعنا يسمىunix.cafe. - وسوف نفترض أيضًا أن المجلد المحلي الذي سنستخدمه لتخزين النسخ الاحتياطية هو
/mnt/website_backups/. - ضع في اعتبارك أن
SRV_BACKUPS_DIRيجب أن يكون مطابقًا لقيمة المتغير$DATADIRالموجود في البرنامج النصيbkpمن جانب الخادم. الذي~/backups. - تذكر أننا افترضنا بالفعل أن مسار
bkpعلى جانب الخادم هو~/bin/bkp.
وهذا يعني أن ما يلي هو تكويننا:
# configuration set SRV_USER deadsoul set SRV_HOST unix.cafe set SRV_BKP_SCRIPT /home/deadsoul/bin/bkp set SRV_BACKUPS_DIR /home/deadsoul/backups/ set LOCAL_ARCHIVE_DIR /mnt/website_backups/
البرنامج النصي النسخ الاحتياطي (BASH version):
#!/usr/bin/bash # configuration SRV_USER='your_username' SRV_HOST='your_server_host' SRV_BKP_SCRIPT='path_to_bkp_on_server' SRV_BACKUPS_DIR='path_to_backups_on_server' # must ends with trailing slash LOCAL_ARCHIVE_DIR='path_to_local_archive' # must ends with trailing slash # ask bkp on server to take a backup ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT" # download the taken backup rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR"
ماذا تفعل؟ (تفسير):
# configuration SRV_USER='your_username' SRV_HOST='your_server_host' SRV_BKP_SCRIPT='path_to_bkp_on_server' SRV_BACKUPS_DIR='path_to_backups_on_server' # must ends with trailing slash LOCAL_ARCHIVE_DIR='path_to_local_archive' # must ends with trailing slash
- لقد شرحنا بالفعل التكوين في version
Expectأعلاه ، تحقق من ذلك.
# ask bkp on server to take a backup ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT" # download the taken backup rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR"
ssh -t $SRV_USER@$SRV_HOST "$SRV_BKP_SCRIPT": تنفيذ البرنامج النصيbkpعلى جانب الخادم عبر ssh.rsync -avhPe 'ssh' $SRV_USER@$SRV_HOST:"$SRV_BACKUPS_DIR" "$LOCAL_ARCHIVE_DIR": تنفيذ الأمرrsyncلتنزيل كافة النسخ الاحتياطية الموجودة.
ترتيب:
لقد تحدثنا بالفعل عن هذا التكوين أعلاه في Expect Version ، لذلك سنستخدمه هنا أيضًا.
# configuration SRV_USER='deadsoul' SRV_HOST='unix.cafe' SRV_BKP_SCRIPT='/home/deadsoul/bin/bkp' SRV_BACKUPS_DIR='/home/deadsoul/backups/' # must ends with trailing slash LOCAL_ARCHIVE_DIR='/mnt/website_backups/' # must ends with trailing slash
استخدامه:
ما عليك سوى فتح نافذة طرفية على جهاز الكمبيوتر المحلي الخاص بك ، واكتب: bkp. هذا هو.
