لماذا لا نجعل عملية النسخ الاحتياطي بسيطة قدر الإمكان؟ أعني باستخدام أمر واحد ، يتم نسخ محتويات الموقع وقاعدة البيانات احتياطيًا عن بُعد ومحليًا. دعونا نرى كيف يمكننا تحقيق ذلك الأمر.
المقدمة:
إذا فكرنا في الأمر ، فسنعلم أننا بحاجة إلى ملفين / نصوص. يجب أن يبقى أحدهم في خادم الموقع (عن بعد) مع وظيفة واحدة ، وهي رعاية عملية النسخ الاحتياطي. بينما يجب أن يكون البرنامج النصي الآخر على جهاز الكمبيوتر الخاص بنا (محليًا) ، والذي يحتوي على وظيفتين. الأول ، هو إخبار البرنامج النصي البعيد ببدء عملية النسخ الاحتياطي. والمهمة الثانية هي تنزيل النسخ الاحتياطية إلى جهاز الكمبيوتر الخاص بنا بمجرد اكتمالها.
نرغب أيضًا في تنظيم النسخ الاحتياطية الخاصة بنا عن طريق تخزينها في مجلدات فرعية تسمى بتاريخ حدوث النسخ الاحتياطي. قد نرغب أيضًا في الاحتفاظ بنسخة من هذه النسخة الاحتياطية على خادم موقعنا كنسخة ثانية. لذا فإن الهدف هو تحقيق كل ذلك من خلال تنفيذ أمر واحد بسيط. يبدو مثيراً؟ رائع ، دعنا نرى كيف نفعل ذلك.
مستودع GitLab:
يمكن العثور عليها في unix.cafe/website-backup. أو استنساخه عن طريق تنفيذ ما يلي في سطر الأوامر:
git clone https://gitlab.com/unix.cafe/website-backup.git
على الجانب البعيد (خادم الموقع):
المتطلبات:
Contents index
تثبيت المتطلبات:
- على 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 إلى الخادم الخاص بك بكلمة مرور أو عبارة مرور رئيسية ولا تريد إدخال كلمة المرور الخاصة بك أكثر من مرة ، فاستخدم
Expect
version. عن طريق نسخ محتواه إلى ملف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" } } interact
puts " "
: طباعة سطر فارغ.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" } } interact
spawn 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
. هذا هو.