<?xml version="1.0"?>
<rss version="2.0"><channel><title>DevOps: Linux &#x644;&#x64A;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/linux/page/7/?d=4</link><description>DevOps: Linux &#x644;&#x64A;&#x646;&#x643;&#x633;</description><language>ar</language><item><title>&#x625;&#x62F;&#x627;&#x631;&#x629; &#x648;&#x633;&#x627;&#x626;&#x637; &#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x627;&#x644;&#x627;&#x641;&#x62A;&#x631;&#x627;&#x636;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x64A;&#x626;&#x629; KVM</title><link>https://academy.hsoub.com/devops/linux/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%88%D8%B3%D8%A7%D8%A6%D8%B7-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D9%8A%D8%A6%D8%A9-kvm-r288/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/kvm-3.png.824c7a435c4294c61119d01e29754ef4.png" /></p>

<p>
	رأينا في الدرسين السابقين من هذه السلسلة ( <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-kvm-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-virtual-machines-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-r286/" rel="">تثبيت KVM وإنشاء آلات افتراضية Virtual machines باستخدامه على أوبونتو</a> و <a href="https://academy.hsoub.com/devops/linux/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D9%8A%D8%A6%D8%A9-kvm-%D8%A8%D9%88%D8%B3%D8%A7%D8%A6%D8%B7-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%B4%D8%A8%D9%83%D9%8A%D8%A9-r287/" rel="">إنشاء آلات افتراضية في بيئة KVM بوسائط تثبيت شبكية</a>) كيفية استخدام <code>virt-manager</code> لإنشاء آلات افتراضيّة وتثبيت أنظمة تشغيل (ضيفة) عليها، انطلاقا من وسيط تخزين <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-kvm-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-virtual-machines-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-r286/" rel="">محلي</a> أو <a href="https://academy.hsoub.com/devops/linux/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D9%8A%D8%A6%D8%A9-kvm-%D8%A8%D9%88%D8%B3%D8%A7%D8%A6%D8%B7-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%B4%D8%A8%D9%83%D9%8A%D8%A9-r287/" rel="">عبر الشبكة</a>. سنتابع في هذا الدرس مع <code>virt-manager</code> ونرى كيفية إدارة وسائط تخزين افتراضيّة Virtual storage devices.
</p>

<p>
	تستخدَم أنظمة التشغيل يوميا وسائط تخزين بنظم ملفات File systems مختلفة، بعضها محلّي Local وآخر يعمل عبر الشبكة. لا توجد عموما اختلافات كبيرة بين مبادئ عمل وسائط التخزين الافتراضية وتلك الملموسة Physical. تُنشأ الأقراص الخاصّة بالآلات الافتراضية في بيئة KVM اعتمادا على أقراص التخزين الملموسة التي يتخاطب معها النظام المُضيف.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="21045" data-unique="swhbu74lf" src="https://academy.hsoub.com/uploads/monthly_2017_02/kvm-3.png.d5d02c5db5f35f8089840ded89338778.png" style="" alt="kvm-3.png"></p>

<p>
	يتعامل نظام التشغيل مع أقراص التخزين حسب تجزئات Partitions (أو Volumes)، ويتكوّن كل قرص صلب من تجزئة أو أكثر. بالنسبة لبيئة KVM فإنها تتعامل مع التجزئات الافتراضية ضمن مجموعات تُسمّى مجامع (أو أحواض) التخزين Storage pools. يجب أولا إنشاء مَجمع تخزين ثم ننشئ به تجزئة جديدة لقرص افتراضي.
</p>

<h2 id="إنشاء-مجامع-تخزين-storage-pools-في-بيئة-kvm">
	إنشاء مجامع تخزين Storage pools في بيئة KVM
</h2>

<p>
	نبدأ أولا بعرض مجامع التخزين المتوفّرة بالنقر على قائمة <strong>Edit</strong> (تعديل) ضمن برنامج <code>virt-manager</code>، ثم <strong>Connection Details</strong> (تفاصيل الاتصال) ونختار تبويب <strong>Storage</strong> (تخزين).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19518" href="https://academy.hsoub.com/uploads/monthly_2016_10/01_connection_details_storage.png.6ce86da78765caa60d2d70dfa228cd83.png" rel=""><img alt="01_connection_details_storage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19518" data-unique="5o8vabmcs" src="https://academy.hsoub.com/uploads/monthly_2016_10/01_connection_details_storage.thumb.png.3f913e41a0cf9a8152acc9d42157cb47.png"></a>
</p>

<p>
	يوجد مبدئيًّا مجمع تخزين باسم <code>default</code> يحفظ التجزئات الافتراضية على المسار <code>var/lib/libvirt/images/</code>. ستلاحظ وجودَ التجزئة الخاصة بنظام التشغيل الضيف الذي أنشأناه في الدرس الأول (اخترنا عند إعداد التخزين في الخطوة 4 مساحة تخزين افتراضية موجودة سلفا). سننشئ في الخطوات التاليّة مجمع تخزين جديدا، بالنقر على زر <code>+</code> في الجانب السفلي الأيسر من النافذة.
</p>

<p>
	تظهر نافذة جديدة لإعطاء اسم لمجمع التخزين واختيار نوعه. يدعم KVM ثمانية أنواع لمجامع التخزين:
</p>

<ul>
<li>
		<code>dir</code>: يحفظ التجزئات الافتراضية ضمن مجلد يوجد في نظام الملفات الذي يستخدمه نظام التشغيل .
	</li>
	<li>
		<code>disk</code>: يستخدم أقراصا صلبة ملموسة لحفظ التجزئات الافتراضية بداخلها.
	</li>
	<li>
		<code>fs</code>: يستخدم تجزئات تخزين مهيّأة سلفا لتخزين التجزئات الافتراضية.
	</li>
	<li>
		<code>netfs</code>: يستخدم وسائط تخزين متشاركة عبر الشبكة، مثل NFS، من أجل حفظ التجزئات الافتراضية.
	</li>
	<li>
		<code>gluster</code>: يحتفظ بالتجزئات الافتراضية ضمن وسيط تخزين ملموس يعمل بنظام الملفات GlusterFS.
	</li>
	<li>
		<code>iscsi</code>: يحفظ التجزئات الافتراضية في وسائط تخزين متوفّرة على الشبكة ببروتوكول ISCSI.
	</li>
	<li>
		<code>scsi</code>: يستخدم وسيط تخزين محلي يعمل بنظام SCSI.
	</li>
	<li>
		<code>lvm</code>: يعتمد على مدير التجزئات المنطقية لتخزين التجزئات الافتراضية.
	</li>
</ul>
<p>
	سنختار في هذه الخطوة استخدام مجمع تخزين من نوع <code>dir</code> (مجلد في نظام التشغيل المُضيف)؛ فهو النوع الأكثر شيوعا ولا يحتاج للتعديل على بنية نظام الملفات المحلية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19519" href="https://academy.hsoub.com/uploads/monthly_2016_10/02_create_storage_pool_1.png.bdc2d809fcbdbcb7822773397e6c662b.png" rel=""><img alt="02_create_storage_pool_1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19519" data-unique="b1g4trjxo" src="https://academy.hsoub.com/uploads/monthly_2016_10/02_create_storage_pool_1.thumb.png.e571121aac90e06fcdb85f24c0976094.png"></a>
</p>

<p>
	لا توجد تقييدات على مكان وجود المجلد الخاص بمجمع التخزين، ولكن من المستحسَن أن يكون على تجزئة منفصلة؛ مع التأكد من الأذون والملكية الخاصة بالمجلّد حتى يمكن ل KVM التعامل معه. تأكد من أن التجزئة التي تريد إنشاء المجمع عليها فارغة، ثم ركّبها على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_1835_7">
sudo mount -t ext4 /dev/sdb4 /mnt/spools/SPool1
</pre>

<p>
	<strong>تحذير:</strong> يمكن أن يؤدي استخدام تجزئة غير فارغة إلى مسح محتوياتها.
</p>

<p>
	حيث <code>dev/sdb4/</code> التجزئة الملموسة و<code>mnt/spools/SPool1/</code> مجلد التركيب. استخدم الأمر <code>lsblk</code> لعرض التجزئات المتوفرة لديك (أو الموجودة على قرص خارجي)؛ كما يمكنك استخدام الأداة الرسومية <code>GParted</code> لنفس الغرض.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19520" href="https://academy.hsoub.com/uploads/monthly_2016_10/03_create_storage_pool_2.png.d54cdec10a6bea4bf566d1bd0636b387.png" rel=""><img alt="03_create_storage_pool_2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19520" data-unique="icn15wfli" src="https://academy.hsoub.com/uploads/monthly_2016_10/03_create_storage_pool_2.thumb.png.7c3807003797ba15d5370391f7d995a4.png"></a>
</p>

<p>
	يظهر في النافذة التالية المسار الذي تريد حفظ تجزئة التخزين الافتراضية فيه. إن كنت تستخدم تجزئة منفصلة فتأكد من ذكر مسار مجلد التركيب (مثلا <code>mnt/spools/SPool1/</code>) هنا.
</p>

<p>
	يظهر مجمع التخزين <code>SPool1</code> بعد إنشائه في القائمة ضمن تبويب <strong>Storage</strong> السابق.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19521" href="https://academy.hsoub.com/uploads/monthly_2016_10/04_connection_details_storage.png.6c2ecca24e3792d715af1e871d400132.png" rel=""><img alt="04_connection_details_storage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19521" data-unique="pxjqsnffb" src="https://academy.hsoub.com/uploads/monthly_2016_10/04_connection_details_storage.thumb.png.aff63e20bcac7725762d978a3c07dc02.png"></a>
</p>

<p>
	أنشأنا مجمع تخزين ويمكننا الآن إنشاء تجزئة تخزين افتراضية عليه؛ ولكن قبل ذلك سنرى نوعا آخر من أنواع مجامع التخزين، وهو <code>fs</code>.
</p>

<p>
	يشير النوع <code>fs</code> إلى أننا نريد استخدام تجزئة قرص ملموسة كاملة، بدلا من مجلد فقط. ستحتاج لإعداد تجزئة قرص ملموس جديدة. تأكد من اسم التجزئة الجديدة (وأنها فارغة) ثم أعدّها لاستخدام نظام الملفات <code>ext4</code> (على سبيل المثال) بالأمر التالي أو ببرنامج إدارة الأقراص المفضّل لديك:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_1835_9">
sudo mkfs.ext4 /dev/sdb6
</pre>

<p>
	أنشئ أيضا مجلدا جديدا (مثلا <code>SPool2</code>) في النظام المُضيف لتركيب القرص عليه.
</p>

<p>
	<strong>ملحوظة:</strong> اكتف بتهيئة التجزئة وإنشاء المجلد دون تركيبها عليه. سيتولى KVM هذه المهمة.
</p>

<p>
	يمكننا الآن إنشاء مجمع تخزين جديد وتسميته مع تحديد نوع المجمع بـ<code>fs</code>.
</p>

<p style="text-align: center;">
	<img alt="05_create_storage_pool_2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19522" data-unique="nprlnelm4" src="https://academy.hsoub.com/uploads/monthly_2016_10/05_create_storage_pool_2.png.887d52d906087fd3846d9305d3bf2796.png"></p>

<p>
	حدد في الخطوة التالية من إنشاء المجمع مسار مجلد التركيب (مثلا <code>mnt/spools/SPool2/</code>) في الخانة <strong>Target Path</strong> (المسار المستهدَف) ومسار التجزئة التي أعددناها سابقا (<code>dev/sdb6/</code> في المثال) في الخانة <strong>Source Path</strong> (المسار المصدَر).
</p>

<p style="text-align: center;">
	<img alt="06_create_storage_pool_2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19523" data-unique="ub0753c7x" src="https://academy.hsoub.com/uploads/monthly_2016_10/06_create_storage_pool_2.png.f19298ffab24e537214ba24057b8c339.png"></p>

<p>
	يظهر مجمع التخزين الجديد في قائمة وسائط التخزين
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19524" href="https://academy.hsoub.com/uploads/monthly_2016_10/07_connection_details_storage.png.a717888d239043598b3aee0293b788d7.png" rel=""><img alt="07_connection_details_storage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19524" data-unique="39rtwq6n9" src="https://academy.hsoub.com/uploads/monthly_2016_10/07_connection_details_storage.thumb.png.0a0733d5bcc8e494932eddf98e1999c1.png"></a>
</p>

<p>
	سنناقش في الدرس الموالي إنشاء نوع آخر من مجامع التخزين (عن طريق سطر الأوامر). ننتقل الآن لإنشاء تجزئة جديدة.
</p>

<h2 id="إضافة-تجزئة-تخزين-افتراضية-إلى-مجمع-تخزين-في-بيئة-kvm">
	إضافة تجزئة تخزين افتراضية إلى مجمع تخزين في بيئة KVM
</h2>

<p>
	توجد صيغ عدّة لتجزئات التخزين. تمكّن هذه الصّيغ من استخدام التجزئة مع مراقبين Hypervisors مختلفين: QEMU، VMware، VirtualBox أو Hyper-V.
</p>

<p>
	حدّد مجمع التخزين الذي تريد إضافة التجزئة إليه (<code>SPool2</code> مثلا) ثم انقر على زر <code>+</code> الموجود تحت بيانات مجمع التخزين أمام عبارة <strong>Volumes</strong> (التجزئات) لتظهر نافذة إضافة تجزئة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19525" href="https://academy.hsoub.com/uploads/monthly_2016_10/08_create_storage_storage_vol.png.83e4761dd5d39079105acf76ae09e737.png" rel=""><img alt="08_create_storage_storage_vol.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19525" data-unique="rltdkmrhl" src="https://academy.hsoub.com/uploads/monthly_2016_10/08_create_storage_storage_vol.thumb.png.a1341aea5a06d21c32a49ac7d7cc3c0b.png"></a>
</p>

<p>
	حدّد اسم التجزئة الجديدة والصيغة <strong>Format</strong> التي تريد استخدامها لإنشاء التجزئة ومساحتها ثم انقر على زر <strong>Finish</strong> (إنهاء). إن كنت تنوي استخدام التجزئة على مراقب آخر غير KVM في ما بعد فتأكد من اختيار صيغة يدعمها ذلك المراقب.
</p>

<p>
	تظهر التجزئة الجديدة ضمن قائمة التجزئات الموجودة في مجمع التخزين <code>SPool2</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19526" href="https://academy.hsoub.com/uploads/monthly_2016_10/09_connection_details_storage.png.275ee6c3dbe614c666f989f978b3f875.png" rel=""><img alt="09_connection_details_storage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19526" data-unique="e05paceuv" src="https://academy.hsoub.com/uploads/monthly_2016_10/09_connection_details_storage.thumb.png.b4feb93a7947ddc759363bcce4155c79.png"></a>
</p>

<p>
	ترجمة - بتصرّف - لمقال <a href="http://www.tecmint.com/manage-kvm-storage-volumes-and-pools/" rel="external nofollow">How to Manage KVM Storage Volumes and Pools for Virtual Machines – Part 3</a> لصاحبه.
</p>
]]></description><guid isPermaLink="false">288</guid><pubDate>Sun, 05 Feb 2017 10:01:59 +0000</pubDate></item><item><title>&#x645;&#x642;&#x62F;&#x645;&#x629; &#x625;&#x644;&#x649; &#x645;&#x633;&#x62A;&#x648;&#x64A;&#x627;&#x62A; RAID</title><link>https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D9%85%D8%B3%D8%AA%D9%88%D9%8A%D8%A7%D8%AA-raid-r298/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/RAID-02.png.28f9d032b93fafe20437e1b27023af1e.png" /></p>

<p id="مقدمة-إلى-مستويات-raid">
	تُحدِّد خصائص مصفوفات RAID بطريقة الضبط والعلاقة بين الأقراص، وهذا يُسمى «مستوى RAID» ‏(RAID level). أكثر مستويات RAID شيوعًا هي:
</p>

<p style="text-align: center;">
	<img alt="RAID-02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20943" data-unique="jxif0cb8l" src="https://academy.hsoub.com/uploads/monthly_2017_01/RAID-02.png.ccae33a7383723106bc405240ae5a21c.png" style=""></p>

<h2 id="raid-0">
	RAID 0
</h2>

<p>
	يدمج مستوى RAID 0 بين جهازين أو أكثر عبر توزيع البيانات عليها، وكما ذكرنا في الدرس السابق (<a href="https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-raid-r294/" rel="">مقدمة إلى اصطلاحات ومفاهيم RAID </a><br>
	) ، التوزيع (striping) هو الآلية التي تُقسِّم البيانات إلى أجزاء (chunks) ثم تكتب تلك الأجزاء بشكلٍ تناوبي على كل قرص في المصفوفة. الفائدة من اتباع هذه الطريقة هي أنَّ البيانات موزَّعة، ويمكن الاستفادة من كل قرص لإجراء عمليات القراءة والكتابة؛ وبالتالي سيكون الأداء النظري لمصفوفة RAID 0 هو حاصل ضرب أداء أحد الأقراص بالعدد الكلي لها (الأداء العملي والحقيقي سيكون أقل من ذلك). ميزة أخرى هي أنَّ المساحة القابلة للاستخدام من المصفوفة هي مجموع مساحات الأقراص المُشكِّلة لها.<br>
	صحيحٌ أنَّ هذا المستوى يوفِّر أداءً رائعًا، إلا أنَّه يعاني من سلبيات ذات أهمية كبيرة. فلمّا كانت البيانات ستُقسَّم بين عدد من الأقراص في المصفوفة، فإن فشل أحد الأجهزة سيؤدي إلى توقف كامل المصفوفة عن العمل وستفقد جميع البيانات. وعلى النقيض من معظم مستويات RAID الأخرى، لا نستطيع إعادة بناء مصفوفات RAID 0، إذ لا توجد مجموعة من الأقراص التي تحتوي معلومات كافية عن محتوى المصفوفة للمساعدة في إعادة بنائها. إذا كنتَ ستستخدم مصفوفات RAID 0، فسيصبح أخذ نسخ احتياطية أمرًا شديد الأهمية، حيث ستفشل المصفوفة في حال فشل أحد الأقراص المكوِّنة لها.
</p>

<h2 id="raid-1">
	RAID 1
</h2>

<p>
	مستوى RAID 1 هو المستوى الذي يُنشِئ نسخةً انعكاسيةً بين جهازَين أو أكثر. أي أنَّ كل المعلومات التي تُكتَب على المصفوفة ستُكتَب بدورها مرتين في كلا القرصين المشكلَين للمجموعة. وهذا يعني أنَّ كل قرص سيحتوي على كامل البيانات الموجودة في المصفوفة، وهذا يوفِّر قدرةً تعويضيةً (redundancy) في حال فشل أحد الأقراص. ستتمكن من الوصول إلى بياناتك في مصفوفات RAID 1 في حال بقي قرصٌ وحيدٌ في المصفوفة سليمًا ويعمل دون مشاكل، ويمكن إعادة بناء المصفوفة باستبدال الأقراص التالفة، ومن ثم ستُستخدَم بقية الأقراص السليمة لنسخ البيانات إلى القرص الجديد.<br>
	هنالك بعض المساوئ لهذا الضبط، فسرعة القراءة النظرية –كما في مستوى RAID 0– يمكن أن تُحسَب بضرب سرعة القراءة لأحد الأقراص بعددها. لكن سرعة الكتابة النظرية القصوى هي سرعة أبطأ قرص في المصفوفة، وذلك لأنَّ كل البيانات يجب أن تُكتَب على كل قرص في المصفوفة. إضافةً إلى ما سبق، المساحة التخزينية الكلية للمصفوفة ستكون مساويةً لمساحة أصغر قرص، لذا إذا كانت لدينا مصفوفة RAID 1 فيها قرصين لهما نفس القدرة التخزينية، فستكون القدرة التخزينية الإجمالية للمصفوفة مساوية لمساحة أحدهما. وإضافة أقراص أخرى سيزيد من عدد النسخ التعويضية للبيانات، ولن يزيد في المساحة المتوافرة.
</p>

<h2 id="raid-5">
	RAID 5
</h2>

<p>
	يملك RAID 5 بعض ميزات مستويي RAID السابقَين، لكن له أداءٌ مختلفٌ وسلبياتٌ مختلفة. ففي مستوى RAID 5، ستوزَّع البيانات على الأقراص بنفس الطريقة التي يتبعها المستوى RAID 0، لكن لكل جزء من البيانات التي تُكتَب على المصفوفة فستُكتَب معلومات parity على أحد الأقراص، والتي هي قيمةٌ محسوبةٌ رياضيًا التي تُستخدَم لتصحيح الأخطاء وإعادة بناء معلومات المصفوفة. سيتم تغيير القرص الذي سيستلم معلومات parity المحسوبة (بدلًا من البيانات الحقيقية) بعد كتابة كل جزء من البيانات.<br>
	لهذا المستوى بعض المزيات المهمة. فمثل بقية المستويات التي توزِّع البيانات على أكثر من قرص، فإن أداء القراءة سيزداد نتيجةً للقدرة على القراءة من عدِّة أقراص معًا. ويمكن لمصفوفات RAID 5 أن تعمل حتى لو فشل أحد الأقراص في المصفوفة. حيث ستسمح معلومات parity بإكمال إعادة بناء البيانات إن حدث ذلك؛ وذلك لأنَّ معلومات parity موزعة (بعض مستويات RAID الأقل شيوعًا تستخدم قرصًا مخصصًا لمعلومات parity)، حيث يملك كل قرصٍ قدرًا متساويًا من معلومات parity. وصحيحٌ أنَّ المساحة التخزينية القابلة للاستخدام في مصفوفات RAID 1 مساوية لمساحة أحد الأقراص (وذلك لأنَّ جميع الأقراص فيها نسخ متماثلة من البيانات)، لكن في RAID 5، يمكن تحقيق القدرة التعويضية بالاستغناء عن المساحة التخزينية لقرصٍ وحيد، فمثلًا إذا كان لدينا أربعة أقراص 100G في مصفوفة RAID 5 فسينتج عنها مساحة تخزينية تساوي 300G (أما 100G الضائعة فستُستَخدم لتخزين معلومات parity).<br>
	وكما في المستويات الأخرى، هنالك سلبياتٌ لمصفوفات RAID 5 التي يجب أخذها بعين الاعتبار. فقد تؤدي إلى تقليل أداء النظام نتيجةً لحساب معلومات parity ديناميكيًا طوال الوقت، وهذا قد يؤثر على الأداء عند كل عملية كتابة على المصفوفة. وإذا فشل أحد الأقراص في المصفوفة وأصبحت المصفوفة ذات حالة منخفضة، فسيؤدي ذلك أيضًا إلى بطئ شديد عند القراءة منها (لأنَّ البيانات الناقصة ستُحسَب من بقية الأقراص). بالإضافة إلى ذلك، عند محاولة إصلاح المصفوفة بعد استبدال القرص التالف، فيجب قراءة كل قرص بأكمله واستخدام المعالج لحساب البيانات الناقصة لإعادة بناء المصفوفة. وهذا قد يُجهِد بقية الأقراص، مما يؤدي أحيانًا إلى فشلٍ إضافيٍ في أحد الأقراص، مما يؤدي في النهاية إلى فقدان البيانات.
</p>

<h2 id="raid-6">
	RAID 6
</h2>

<p>
	يَستخدم مستوى RAID 6 بنيةً قريبةً من مستوى RAID 5، لكن مع مضاعفة كمية معلومات parity. هذا يعني أنَّ المصفوفة ستصمد حتى لو حدث عطب بقرصين. وهذه ميزة مهمة جدًا لزيادة احتمال حدوث عطب آخر أثناء عملية إعادة بناء المصفوفة عند حدوث خطأ. وفي هذا المستوى –كغيره من المستويات التي تستخدم التوزيع– سيكون أداء القراءة جيد إجمالًا. وجميع ميزات RAID 5 تنطبق أيضًا على RAID 6.<br>
	أما مساوئ هذا المستوى، فهي استخدام مساحة تخزينية أكبر لمعلومات parity، وهذا يعني أنَّ المساحة الإجمالية للمصفوفة هي مجموع مساحات جميع الأقراص المكوِّنة لها منقوصًا منها مساحة قرصين. إضافةً إلى أنَّ العمليات الحسابية اللازمة لإنشاء معلومات parity لمستوى RAID 6 أكثر تعقيدًا من RAID 5، مما يعني أداءً أسوأ للكتابة مقارنةً مع RAID 5. يعاني مستوى RAID 6 من نفس المشاكل التي تحدث في RAID 5 عندما تصبح المصفوفة بحالة منخفضة، لكن وجود قرص إضافي للتعويض سيقل احتمال حدوث مشاكل إضافية تؤدي إلى حذف جميع البيانات عند عمليات إعادة البناء.
</p>

<h2 id="raid-10">
	RAID 10
</h2>

<p>
	يمكن تطبيق مستوى RAID 10 بعدِّة طرائق، والتي ستؤثِّر على خصائصه:
</p>

<h3 id="مستويا-1-و-0-متشعبان">
	مستويا 1 و 0 متشعبان
</h3>

<p>
	تقليديًا، يُشير مستوى RAID 10 إلى مستوى متشعب، والذي يُنشَأ بضبط مصفوفتَي RAID 1 أو أكثر أولًا، ثم استخدام تلك المصفوفات كمكونات لإنشاء مصفوفة RAID 0 موزّعة. ويدعى هذا المستوى حاليًا أحيانًا باسم RAID 1+0 للإشارة إلى هذه العلاقة. وبسبب تصميم هذا المستوى، فإن العدد الأدنى للأقراص هو أربعة وذلك لإنشاء مصفوفة RAID 1+0 (أي مستوى RAID 0 يستعمل مصفوفتَي RAID 1 تتألف كلٌ منهما على قرصين).<br>
	تملك مصفوفات RAID 1+0 أداءً عاليًا شبيهًا بمصفوفات RAID 0، لكن بدلًا من الاعتماد على أقراص مفردة لتوزيع البيانات، فسيتم استخدام مصفوفة منسوخة نسخًا انعكاسيًا (mirrored array)، مما يعني توفير قدرة تعويضية. يمكن أن يتحمل هذا النوع من الضبط أيّة أخطاء ومشاكل في الأقراص لطالما بقي قرصٌ وحيدٌ يعمل في كل مصفوفة RAID 1 مُشكِّلة للمصفوفة النهائية. يمكن أن يتحمل هذا المستوى عددًا مختلفًا من المشاكل اعتمادًا على مكان وقوعها.<br>
	ولأنَّ مصفوفات RAID 1+0 توفِّر أداءً عاليًا وقدرةً تعويضيةً، فهي خيارٌ ممتازٌ إن لم تكن مقيدًا بعددٍ معيّنٍ من الأقراص.
</p>

<h3 id="raid-10-عبر-mdadm">
	RAID 10 عبر mdadm
</h3>

<p>
	لدى برمجية mdadm في لينكس نسخةٌ خاصةٌ بها من RAID 10، والتي تحمل نفس فوائد RAID 1+0 لكن تُغيّر في طريقة تنفيذها لكي تكون مرنةً أكثر وتوفِّر ميزاتٍ إضافيةٍ.<br>
	وكما في مستوى RAID 1+0، مستوى RAID 10 في <code>mdadm</code> يسمح بتوزيع البيانات ونسخها أكثر من مرة. لكن الأقراص لن تُرتَّب كمجموعتَين منسوختين نسخًا انعكاسيًا، وإنما سيقرِّر مدير النظام عدد النسخ التي ستُكتَب على المصفوفة. ستُجزَّأ البيانات وتُكتَب على المصفوفة بأكثر من نسخة، مع الحرص على أن تُكتَب كل نسخة من البيانات على قرصٍ فيزيائيٍ منفصل. والنتيجة النهائية هو وجود نفس العدد من النسخ، لكن طريقة بناء المصفوفة تختلف (أي لن يكون فيها «تشعب»).<br>
	هذا الضبط لمستوى RAID 10 له ميزات تجعله متفوقًا عن RAID 1+0، فلأنه لا يعتمد على تشعّب المصفوفات فذلك يعني أننا نستطيع استخدام رقم فردي من الأقراص ويمكن أيضًا تقليل عدد الأقراص الأدنى (ليصبح 3 فقط). يمكن أيضًا ضبط عدد النسخ. وستصبح الإدارة أبسط لأنك ستحتاج إلى إدارة مصفوفة وحيدة، ويمكنك استخدام أقراص بديلة (كقطع غيار) لكامل المصفوفة، بدلًا من إمكانية استخدامها لمصفوفة متشعبة وحيدة.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	أكثر مستوى من مستويات RAID يناسب خادومك يعتمد تمامًا على حالات استخدامك له وعلى هدفك من المصفوفة. التكلفة والقيود التي يضعها العتاد سيؤثران أيضًا على عملية تقرير مستوى RAID المناسب.<br>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/an-introduction-to-raid-terminology-and-concepts" rel="external nofollow">An Introduction to RAID Terminology and Concepts</a> لصاحبه Justin Ellingwood
</p>
]]></description><guid isPermaLink="false">298</guid><pubDate>Tue, 31 Jan 2017 10:37:00 +0000</pubDate></item><item><title>&#x645;&#x642;&#x62F;&#x645;&#x629; &#x625;&#x644;&#x649; &#x627;&#x635;&#x637;&#x644;&#x627;&#x62D;&#x627;&#x62A; &#x648;&#x645;&#x641;&#x627;&#x647;&#x64A;&#x645; RAID</title><link>https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-raid-r294/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/RAID.png.a1a41d505b87e1ddb406c9e4e22974a7.png" /></p>

<h2 id="مقدمة-إلى-اصطلاحات-ومفاهيم-raid">
	تمهيد
</h2>

<p>
	من المهم أن تأخذ طريقة التخزين بعين الاعتبار عندما تضبط خادومًا، إذ أنَّ أغلبية المعلومات المهمة التي تهتمُ أنت ومستخدموك بها ستُكتَب في مرحلةً ما إلى وسيط تخزين للحصول عليها لاحقًا. ستستفيد من الأقراص المستقلة إذا كانت احتياجاتك بسيطة، لكن إن أردتَ الحصول على أداءٍ عالٍ أو ضمانٍ لعدم فقدان بياناتك، فعندئذٍ ستستفيد من تقنيات مثل RAID.<br>
	سنتحدث في هذا الدرس عن اصطلاحات RAID ومفاهيمها الشائعة، وسنناقش بعض ميزات (ومساوئ) استخدام مصفوفات RAID، وسنتحدث عن الاختلافات بين طرائق تنفيذ تقنية RAID.
</p>

<p style="text-align: center;">
	<img alt="RAID.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20832" data-unique="yo84dhqoc" src="https://academy.hsoub.com/uploads/monthly_2017_01/RAID.png.d8ecd473122fa79cb7b0b7b6c8916c80.png"></p>

<h2 id="ما-هي-مصفوفة-raid">
	ما هي مصفوفة RAID؟
</h2>

<p>
	ترمز الكلمة RAID إلى «<strong>R</strong>edundant <strong>A</strong>rrays of <strong>I</strong>ndependent <strong>D</strong>isks» وهي تعني «مصفوفة الأقراص التعويضية المستقلة»، أي استخدام عدِّة أقراص بأنماط مختلفة مما يمنح مدراء الأنظمة أداءً أفضل أو قدرةً تعويضيةً (ضد فشل الأقراص) مقارنةً بمجموعةٍ من الأقراص التي تعمل بمفردها. يمكن تطبيق RAID على الأقراص الخام أو على الأقسام الموجودة في قرصٍ ما.
</p>

<h2 id="متى-يفضل-استخدام-raid">
	متى يُفضَّل استخدام RAID؟
</h2>

<p>
	الفائدة الأساسية من مصفوفات RAID هي القدرة على تعويض فقدان البيانات والزيادة في الأداء.<br>
	القدرة التعويضية تعني زيادةً في إتاحية (availability) البيانات المخزنة، وهذا يعني أننا سنتمكن من الوصول إلى المعلومات المخزنة عند حدوث بعض الحالات مثل فشل أحد أقراص التخزين، وسيتمكن النظام من إكمال عمله إلى أن يُستبَدل القرص المعطوب. لكن هذا لا يعني أنَّ هذه هي آلية نسخ احتياطي (يجب أخذ نسخ احتياطية لمصفوفات RAID كغيرها من أنواع التخزين)، وإنما الغرض من هذه الآلية هو تقليل الانقطاعات عند حدوث مشكلة.<br>
	فائدةٌ أخرى رئيسيةٌ توفرها مصفوفات RAID في بعض الحالات هي الزيادة في الأداء، فعادةً ستكون سرعة الكتابة أو القراءة على وسائط التخزين محدودة (ومرتبطة) بسرعة الكتابة على قرصٍ وحيد، أما البيانات في مصفوفات RAID فهي إما موجودة نفسها في أكثر من قرص (redundant) أو موزعة على أكثر من قرص (distributed)، وهذا يعني أننا نستطيع استخدام عدِّة أقراص لكل عملية قراءة مما يزيد من كمية البيانات التي يمكن قراءتها في الثانية؛ ويمكن أيضًا تحسين سرعة عمليات الكتابة في بعض حالات الضبط التي يمكن فيها كتابة قسم من البيانات على كل قرص.<br>
	بعض الجوانب السلبية في مصفوفات RAID تتضمن زيادةً في تعقيد عملية الإدارة وعادةً تؤدي إلى إنقاص المساحة التخزينية المتوافرة. وهذا يعني تكاليف إضافية يجب دفعها للحصول على نفس مقدار المساحة التخزينية القابلة للاستخدام. هنالك مصاريف أخرى تتضمن استخدام قطع عتاديّة خاصة عندما لا تريد إدارة المصفوفة عبر أدواتٍ برمجيةٍ فقط.<br>
	إحدى السلبيات الأخرى للمصفوفات المضبوطة للحصول على أداءٍ عالٍ دون قدرة تعويضية هي الزيادة في احتمال فقدات البيانات، حيث تعتمد البيانات المخزنة على الأقراص في تلك الحالات على أكثر من وسيط تخزين وحيد، مما يزيد من احتمال فقدان البيانات نتيجة عطب في أحد الأقراص.
</p>

<h2 id="مصفوفات-raid-التي-تعتمد-على-العتاد-والتي-تعتمد-على-البرمجيات-والتي-تعتمد-على-البرمجيات-بمساعدة-العتاد">
	مصفوفات RAID التي تعتمد على العتاد، والتي تعتمد على البرمجيات، والتي تعتمد على البرمجيات بمساعدة العتاد
</h2>

<p>
	يمكن إنشاء وإدارة مصفوفات RAID بمختلف التقنيات. وهي:
</p>

<h3 id="مصفوفات-raid-التي-تعتمد-على-العتاد">
	مصفوفات RAID التي تعتمد على العتاد
</h3>

<p>
	هنالك قطعٌ عتاديةٌ مخصصة تسمى «متحكمات RAID» ‏(RAID controllers) أو «بطاقات RAID» ‏(RAID cards) يمكن أن تستعمل لإعداد وإدارة مصفوفات RAID بمعزل عن نظام التشغيل، وهذا معروفٌ بالمصطلح «hardware RAID». تملك متحكمات RAID العتادية معالجًا منفصلًا لإدارة أجهزة RAID.<br>
	لمصفوفات RAID التي تعتمد على العتاد عدِّة ميزات، نذكر منها:
</p>

<ul>
<li>
		الأداء: متحكمات RAID العتادية (الحقيقة) لا تأخذ من وقت المعالج لإدارة الأقراص الموجودة ضمن المصفوفة. وهذا يعني أنَّك لن تُسبِّب تقليل أداء الخادوم لإدارة أجهزة التخزين. توفِّر المتحكمات ذات الجودة العالية تخزينًا مؤقتًا كبيرًا وله أثرٌ كبيرٌ على الأداء.
	</li>
	<li>
		إخفاء تعقيدات المصفوفة: ميزة أخرى لاستخدام متحكمات RAID هي أنَّها تخفي طريقة ترتيب الأقراص وإدارتها عن نظام التشغيل، حيث ستُمثِّل متحكماتُ RAID المصفوفةَ على أنها وحدة تخزينٍ منطقيةٍ وحيدةٍ. وليس من الضروري أن يفهم نظام التشغيل طريقة ترتيب مصفوفة RAID؛ إذ أنَّه سيتعامل مع كامل المصفوفة على أنها قرصٌ وحيدٌ.
	</li>
	<li>
		سيُتاح استخدام المصفوفة عند الإقلاع: بسبب أنَّ المصفوفة مدارة بشكلٍ كامل عتاديًا دون تدخل البرمجيات، فهذا يعني أنها متاحة الاستخدام عند الإقلاع، مما يسمح بإنشاء نظام الملفات الرئيسي (الذي سيُثبَّت داخله نظام التشغيل) داخل مصفوفة RAID.<br>
		لكن هنالك بعض السلبيات لمصفوفات RAID التي تعتمد على العتاد:
	</li>
	<li>
		احتكار الشركات: لأن مصفوفات RAID العتادية مدارةٌ من برمجيات تجارية موجودة داخل العتاد، فهذا يعني أنَّنا يجب أن نستعمل المصفوفة مع نوع العتاد الذي أنشأها فقط؛ فلو تعطل متحكم RAID، ففي أغلب الحالات يجب أن نضع شريحة مماثلة أو شريحة متوافقة مع الشريحة القديمة بدلًا عنه. يَنصح بعض مدراء الأنظمة بشراء أكثر من متحكم RAID من نفس النوع كاحتياطٍ في حال حدثت مشكلة.
	</li>
	<li>
		الكلفة العالية: متحكمات RAID ذات الجودة العالية تكون ذات سعر مرتفع عادةً.
	</li>
</ul>
<h3 id="مصفوفات-raid-التي-تعتمد-على-البرمجيات">
	مصفوفات RAID التي تعتمد على البرمجيات
</h3>

<p>
	يمكن أيضًا ضبط RAID داخل نظام التشغيل نفسه. ولأنَّ العلاقة بين الأقراص ستُعرَّف وتُضبَط داخل نظام التشغيل عوضًا عن استخدام جهاز عتادية منفصل، فستسمى تلك المصفوفات بمصفوفات «software RAID».<br>
	بعض ميزات مصفوفات RAID البرمجية:
</p>

<ul>
<li>
		المرونة: لمّا كانت مصفوفات RAID التي تعتمد على البرمجيات تُدار داخل نظام التشغيل، فيمكن بسهولة ضبط أجهزة التخزين المتاحة دون تغيير شيء في ضبط العتاد. عملية إنشاء مصفوفات RAID في لينكس هي عملية مرنة للغاية، حيث يُسمَح بضبط مختلف أنواع ومستويات RAID.
	</li>
	<li>
		مفتوحة المصدر: البرمجيات التي نستعملها لضبط مصفوفات RAID في الأنظمة مفتوحة المصدر مثل لينكس و FreeBSD هي برمجيات مفتوحة المصدر أيضًا، وضبط المصفوفات متاحٌ لك وغير مخفي، ويمكن بكل سهولة قراءته وتطبيقه على أنظمة أخرى. فمثلًا، إذا كانت لدينا مصفوفة RAID أنشأناها على نظام أوبنتو، فسنتمكن ببساطة من نقلها إلى خادوم CentOS لاحقًا. هنالك احتمالٌ ضئيلٌ في أنَّك ستفقد الوصول إلى بياناتك بسبب بعض الاختلافات بين البرمجيات.
	</li>
	<li>
		لا توجد تكلفة إضافية: لا يتطلب إنشاء مصفوفات RAID برمجية أيّة قطع عتادية خاصة، لذا لن تكون هنالك تكلفة إضافية على خادومك عند استخدامها.<br>
		بعض سلبيات استخدام مصفوفات RAID البرمجية:
	</li>
	<li>
		التبعية للبرمجيات: صحيحٌ أنَّ مصفوفات RAID البرمجية غير مرتبطة بعتاد معيّن، لكن عادةً سترتبط ببرمجية معيّنة التي أنشأتها فيها. فمثلًا يستخدم لينُكس <code>mdadm</code> بينما FreeBSD يستعمل مصفوفات RAID مبنية على GEOM، ولنظام ويندوز له نسخةٌ خاصةٌ به من البرمجيات التي تُتيح إنشاء مصفوفات RAID برمجية. وعلى الرغم من أنَّ مختلف نسخ البرمجيات المفتوحة المصدر يمكن أن تُصدِّر ضبطها فيما بينهما، إلا أنَّه لا يحتمل أن تتوافق الصيغة نفسها مع بقية برمجيات RAID.
	</li>
	<li>
		مشاكل في الأداء: قديمًا كانوا ينتقدون مصفوفات RAID البرمجية لأنها تُسبِّب بحملٍ إضافيٍ على النظام. فسيُستعمَل المعالج المركزي والذاكرة لإدارة المصفوفة، والتي كانت يمكن أن تُستعمَل لأمورٍ أخرى. لكن البرمجيات مثل <code>mdadm</code> التي تعمل على عتادٍ حديث قد أطاحت بهذا المخاوف، أي أنَّ استعمال المعالج يكون أصغريًا في أغلبية الحالات ولا نأخذه بعين الاعتبار.
	</li>
</ul>
<h3 id="مصفوفات-raid-التي-تعتمد-على-البرمجيات-بمساعدة-العتاد">
	مصفوفات RAID التي تعتمد على البرمجيات بمساعدة العتاد
</h3>

<p>
	النوع الثالث من مصفوفات RAID يدعى «hardware-assisted software RAID» أو «firmware RAID» أو «fake RAID». عمومًا يوفر هذا النوع ميزات RAID بتضمينه داخل اللوحة الأم أو عبر بطاقات RAID رخيصة الثمن. يتم تطبيق هذا النوع من المصفوفات عبر استخدام برمجيات على المتحكم أو البطاقة لإدارة مصفوفة RAID، لكنه يستخدم وحدة المعالجة المركزية لتشغيل تلك البرمجيات.<br>
	ميزات هذا النوع من المصفوفات:
</p>

<ul>
<li>
		<p>
			دعم إقلاع أكثر من نظام تشغيل: وذلك لأنَّ مصفوفة RAID ستعمل عند الإقلاع، لذا يمكن استخدام أكثر من نظام تشغيل للمصفوفة، وهذا غير ممكن إذا استعملنا مصفوفات RAID برمجية.<br>
			من سلبياتها:
		</p>
	</li>
	<li>
		<p>
			دعم محدود لمستويات RAID: عادةً تدعم RAID 0 أو RAID 1 فقط.
		</p>
	</li>
	<li>
		تتطلب عتادًا خاصًا: مثل مصفوفات RAID العتادية، هذا النوع مقيدٌ بالعتاد الذي أنشأه ويديره، وهذه مشكلة كبيرة في حال كان موجودًا ضمن اللوحة الأم، فلو فشل متحكم RAID أو تعطل، فهذا يعني أنَّ عليك استبدال اللوحة الأم كلها لكي تستطيع الوصول مرةً أخرى إلى بياناتك.
	</li>
	<li>
		مشاكل في الأداء: مثل مصفوفات RAID العتادية، لا يوجد هنا معالج خاص بإدارة RAID، ويجب أن يتشارك المتحكم مع نظام التشغيل باستخدام المعالج المركزي.<br>
		أغلبية مدراء الأنظمة يبقون بعيدين عن هذا النوع من مصفوفات RAID، لأنها تعاني من اجتماع مشاكل النوعَين الآخرَين.
	</li>
</ul>
<h2 id="الاصطلاحات-المستخدمة-عند-الحديث-عن-مصفوفات-raid">
	الاصطلاحات المستخدمة عند الحديث عن مصفوفات RAID
</h2>

<p>
	سيساعدك التعرف على بعض هذه الاصطلاحات على فهم RAID بشكل أفضل. هذه بعض المصطلحات الشائعة التي قد تصادفك:
</p>

<ul>
<li>
		مستوى RAID ‏(RAID level): يشير «مستوى RAID» إلى العلاقة التي تجمع أجهزة التخزين. يمكن ضبط الأقراص بعدِّة طرائق، مما يؤدي إلى خصائص مختلفة للتعويض وللأداء.
	</li>
	<li>
		التوزيع (Striping): «التوزيع» هو عملية تقسيم البيانات المكتوبة على المصفوفة إلى أكثر من قرص. تُستخدَم هذه التقنية من مختلف مستويات RAID. عندما توزَّع البيانات على المصفوفة، فستُقسَّم إلى أجزاء صغيرة، ثم يكُتَب كل جزء إلى قرص واحد أو أكثر من الأقراص المُشكِّلة للمصفوفة.
	</li>
	<li>
		حجم الجزء (Chunk Size): عند توزيع البيانات، سيُحدِّد «حجم الجزء» مقدار البيانات التي سيحتوي كل جزء عليها. وتعديل حجم الجزء ليُطابِق خصائص الدخل والخرج التي تتوقعها قد يساعد في زيادة أداء المصفوفة.
	</li>
	<li>
		آلية تعادل القيمة (Parity): هذه آلية يتم إنجازها عبر حساب المعلومات من كتل البيانات (data blocks) المكتوبة إلى المصفوفة. وقد تستخدم معلومات parity لإعادة بناء البيانات إذا فشل أحد الأقراص. قد توضع معلومات parity في قرص منفصل عن الأقراص التي تحتوي البيانات التي تُحسَب بيانات parity منها، وتوزَّع في أغلبية حالات الضبط على عدِّة أجهزة للمقدرة على تعويض فشل أحد الأقراص ولزيادة الأداء.
	</li>
	<li>
		مصفوفات ذات الحالة المخفَّضة (Degraded Arrays): يمكن أن تعاني المصفوفات التي لها قدرة تعويضية (redundancy) أنواعًا مختلفةً من فشل الأقراص دون خسارة البيانات. فعندما تخسر المصفوفة قرصًا لكنها تستطيع إكمال عملها، فيُقال أنَّها أصبحت «بحالة مُخفَّضة» (degraded mode). يمكن إعادة بناء المصفوفات ذات الحالة المخفَّضة لترجع كما كانت بعد استبدال القرص المعطوب، لكنها قد تعاني من أداءٍ منخفض أثناء تلك الفترة.
	</li>
	<li>
		إعادة المزامنة (Resilvering أو Resyncing): «إعادة المزامنة» هو المصطلح المستخدم لإعادة بناء مصفوفة ذات الحالة المخفَّضة. واعتمادًا على ضبط RAID ونوع الفشل، سنتمكن من إجراء عملية إعادة المزامنة إما بنسخ البيانات من الملفات الموجودة في المصفوفة، أو عبر حساب البيانات باستخدام معلومات parity‏ (parity information).
	</li>
	<li>
		المصفوفات المتشعبة (Nested Arrays): يمكن دمج مجموعات من مصفوفات RAID في مصفوفات أكبر. ونفعل ذلك عادةً للاستفادة من ميزات مستويي RAID أو أكثر. عادةً تُستخدَم المصفوفات ذات القدرة التعويضية (مثل RAID 1 أو RAID 5) كمكونات لإنشاء مصفوفة RAID 0 لزيادة الأداء.
	</li>
	<li>
		الامتداد (Span): للأسف، مصطلح «الامتداد» له معانٍ مختلفة عندما نتحدث عن المصفوفات.<br>
		..- في سياقات معيّنة، «الامتداد» يعني وصل قرصين أو أكثر مع بعضهما لتمثيلهما كجهاز منطقي وحيد، بدون تحسين في الأداء أو القدرة التعويضية. وهذا يُعرَف أيضًا بالترتيب الخطي (linear arrangement) عند التعامل مع برمجية <code>mdadm</code> في لينكس.<br>
		..- يمكن أن يشير «الامتداد» إلى المصفوفات التي تُجمَّع مع بعضها لإنشاء مستوى جديد من مستويات RAID وذلك في المصفوفات المتشعبة، مثل المصفوفات من المستوى RAID 10 (أي RAID 1+0).
	</li>
	<li>
		التحقق (Scrubbing أو Checking): هي عملية قراءة كل كتلة في المصفوفة للتأكد من عدم وجود أخطاء. وهذا يساعد في التأكد من أنَّ البيانات متماثلة في أكثر من وسيط تخزين، وسيمنع ذلك من حدوث أخطاء قد تؤدي إلى تلف في البيانات، وخصوصًا خلال العمليات الحساسة مثل إعادة بناء المصفوفة.<br>
		ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/an-introduction-to-raid-terminology-and-concepts" rel="external nofollow">An Introduction to RAID Terminology and Concepts </a>لصاحبه Justin Ellingwood
	</li>
</ul>
]]></description><guid isPermaLink="false">294</guid><pubDate>Wed, 25 Jan 2017 12:58:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x622;&#x644;&#x627;&#x62A; &#x627;&#x641;&#x62A;&#x631;&#x627;&#x636;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x64A;&#x626;&#x629; KVM &#x628;&#x648;&#x633;&#x627;&#x626;&#x637; &#x62A;&#x62B;&#x628;&#x64A;&#x62A; &#x634;&#x628;&#x643;&#x64A;&#x629;</title><link>https://academy.hsoub.com/devops/linux/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D9%8A%D8%A6%D8%A9-kvm-%D8%A8%D9%88%D8%B3%D8%A7%D8%A6%D8%B7-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%B4%D8%A8%D9%83%D9%8A%D8%A9-r287/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/kvm.png.d100f05a244bc22b5c7585a479d10b4a.png" /></p>

<p>
	يتناول هذا المقال، الثاني من سلسلة من أربعة أجزاء، كيفيّة توزيع آلات افتراضيّة عبر وسائط شبكة في بيئة تستخدم KVM. تأكد - قبل تنفيذ الخطوات المشروحة هنا - من تثبيت <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-kvm-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-virtual-machines-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-r286/#%D8%A7%D9%84%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA" rel="">المتطلّبات</a> المذكورة في الجزء الأول من السلسلة.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="20750" data-unique="mv5oiytuk" src="https://academy.hsoub.com/uploads/monthly_2017_01/kvm.png.7fc4d0aebb2631f486bc7f3519828f4d.png" style="" alt="kvm.png"></p>

<h2 id="تثبيت-نظام-تشغيل-عن-طريق-خادوم-ftp-في-بيئة-kvm">
	تثبيت نظام تشغيل عن طريق خادوم FTP في بيئة KVM
</h2>

<p>
	سنثبّت لأغراض هذا الدرس خادوم FTP على النظام المُضيف؛ وذلك باتباع الخطوات التالية (راجع درس <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D8%B5%D9%8A%D8%A8-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-ftp-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r196/" rel="">كيفية تنصيب وإعداد خادوم FTP على أوبنتو</a> لتفاصيل أكثر عن إعداد خادوم FTP). سنكتفي هنا بالأوامر الأساسية للحصول على الخادوم وتثبيت نظام ضيف على آلة افتراضية عن طريقه.
</p>

<p>
	للتثبيت:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_7">
$ sudo apt install vsftpd
</pre>

<p>
	ثم نعدّل ملف الإعداد <code>etc/vsftpd.conf/</code> للسماح بالوصول المجهول لخادوم FTP:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_9">
$ sudo nano /etc/vsftpd.conf
</pre>

<p>
	نغيّر قيمة التعليمة <code>anonymous_enable</code> من <code>NO</code> إلى <code>YES</code>؛ ثم نعيد <a href="https://academy.hsoub.com/devops/linux/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-systemd-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%AE%D8%AF%D9%85%D8%A7%D8%AA%D8%8C-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-units%D8%8C-%D9%88%D8%A7%D9%84%D9%8A%D9%88%D9%85%D9%8A%D8%A7%D8%AA-journal-r130/" rel="">تشغيل الخادوم</a>:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_11">
$ sudo systemctl restart vsftpd.service
</pre>

<p>
	إن أردنا مشاركة ملفات عن طريق خادوم FTP فيمكننا وضعها على المسار <code>‎/srv/ftp</code>.
</p>

<p>
	جهّزنا خادوم FTP لمشاركة الملفات؛ حان الآن وقت اختيار ملف ISO الخاص بنظام التشغيل الذي نريد تثبيته على الآلة الافتراضية (النظام الضّيف)؛ ونحدّد نقطة تركيب Mount point ليُركَّب عليها هذا الملف:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_13">
$ sudo mount -t iso9660 -o ro ISO_FILE  MOUNT_POINT
</pre>

<p>
	تشير <code>ISO_FILE</code> إلى المسار الذي يوجد عليه ملف ISO و<code>MOUNT_POINT</code> إلى مسار مجلد التركيب.
</p>

<p>
	<strong>ملحوظة:</strong> تمثّل ملفات ISO نسخا خامة من أقراص صلبة ويجب تركيبها على نظام الملفات File system حتى يمكن لنظام التشغيل التعامل معها. يتعامل نظام التشغيل مع المجلَّد الذي رُكِّب عليه المحتوى كما لو كان يقرأ البيانات من قرص مًدمَج (CD أو DVD). نحدّد أثناء التركيب نظام الملفات المناسب للتعامل مع ملف ISO وهو <code>iso9660</code>.
</p>

<p>
	لا يمكن لحدّ الساعة الوصول إلى محتويات الملفّ أعلاه عن طريق FTP؛ إذ أنها لا توجد في المسار الذي يمكن لخادوم تشارك الملفات القراءة منه. ننشئ مجلدا جديدا على المسار <code>‎/srv/ftp</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_15">
$ sudo mkdir /srv/ftp/ubuntu-14.04
</pre>

<p>
	ثم ننقل إليه محتويات ملفّ ISO انطلاقا من نقطة التركيب:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_17">
$ sudo cp -r /mnt/ubuntu-14.04/* /srv/ftp/ubuntu-14.04/
</pre>

<p>
	حيثُ <code>mnt/ubuntu-14.04/</code> هي نقطة التركيب (<code>MOUNT_POINT</code>) السابقة. نتأكد من أن <a href="https://academy.hsoub.com/devops/linux/%D8%B6%D8%A8%D8%B7-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-%D9%88%D8%A7%D9%84%D9%85%D8%AC%D9%85%D9%88%D8%B9%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r78/" rel="">مجموعة المستخدمين</a> <code>ftp</code> هي المالكة للمجلد <code>ubuntu-14.04</code> الذي أنشأناه للتو حتى يمكن لخادوم FTP قراءة محتوياته:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_19">
$ sudo chown -R :ftp /srv/ftp/ubuntu-14.04/
</pre>

<p>
	يمكننا الآن استخدام أداة <code>virt-manager</code> لإنشاء آلات افتراضية تستخدم وسيط التثبيت الموجود على خادوم تشارك الملفات. تظهر عند طلب إنشاء آلة افتراضية جديدة النافذة التالية.
</p>

<p style="text-align: center;">
	<img alt="01_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19502" data-unique="conaxtrhx" src="https://academy.hsoub.com/uploads/monthly_2016_10/01_new_vm.png.68180fe86639f289b82a4957379d5d08.png"></p>

<p>
	نحدّد خيار التثبيت عبر الشبكة <strong>Network Install</strong> وننتقل للخطوة الموالية.
</p>

<p>
	نحدّد في هذه الخطوة المسار URL الذي يوجد عليه وسيط التثبيت. بما أننا نريد الوصول إلى خادوم FTP فالمسار سيكون حسب الصيغة التالية:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_21">
ftp://ip_or_host/folder
</pre>

<p>
	حيثُ <code>ip_or_host</code> عنوان IP الخاص بخادوم تشارك الملفات أو اسم المضيف Host الخاص به؛ و<code>folder</code> المجلّد حيث توجد ملفات نظام التشغيل الذي نريد تثبيته على الآلة الافتراضية (مجلد <code>ubuntu-14.04</code> الموجود على خادوم تشارك الملفات).<br>
	تذكّر أننا في الدرس السابق ثبّتنا <a href="https://academy.hsoub.com/devops/linux/%d8%aa%d8%ab%d8%a8%d9%8a%d8%aa-kvm-%d9%88%d8%a5%d9%86%d8%b4%d8%a7%d8%a1-%d8%a2%d9%84%d8%a7%d8%aa-%d8%a7%d9%81%d8%aa%d8%b1%d8%a7%d8%b6%d9%8a%d8%a9-virtual-machines-%d8%a8%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85%d9%87-%d8%b9%d9%84%d9%89-%d8%a3%d9%88%d8%a8%d9%88%d9%86%d8%aa%d9%88-r286/#%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-kvm-%D9%88%D9%86%D8%B4%D8%B1-%D8%A7%D9%84%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9" rel="">حزمة <code>bridge-utils</code></a> وذكرنا أنها تنشئ جسرا يعمل بين الآلات الافتراضية (النظام الضّيف) والنظام المُضيف. ستلاحظ بعد تثبيت الحزمة ظهور واجهة شبكة جديدة لديك على النظام المُضيف (حيثُ ثبتتنا KVM وأدواته) باسم <code>virbr0</code>. يمكن للأجهزة الافتراضية التواصل مع النظام المضيف عن طريق هذه الواجهة؛ لذا سنحصُل على عنوانها بتنفيذ الأمر التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_24">
$ ip -4 a show
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
4: virbr0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
    valid_lft forever preferred_lft forever
</pre>

<p>
	يظهر من نتيجة الأمر أعلاه أن الواجهة <code>vibr0</code> لديها العنوان <code>192.168.122.1</code> (قد يختلف العنوان لديك). يصبح عنوان المجلّد حيث توجد ملفات التثبيت على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_26">
ftp://192.168.122.1/ubuntu-14.04
</pre>

<p style="text-align: center;">
	<img alt="02_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19503" data-unique="o14pet5du" src="https://academy.hsoub.com/uploads/monthly_2016_10/02_new_vm.png.69c6c1c33cf58ea4d3c1c4852b4c1493.png"></p>

<p>
	وهو العنوان الذي أعطيناه للأداة <code>virt-manager</code> كما في الصورة أعلاه. تشبه الخطوات الموالية (من 3 إلى 5) الخطوات المذكورة في <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-kvm-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-virtual-machines-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-r286/" rel="">الجزء الأول</a> من هذه السلسلة.
</p>

<h2 id="تثبيت-نظام-تشغيل-عن-طريق-خادوم-وب-في-بيئة-kvm">
	تثبيت نظام تشغيل عن طريق خادوم وِب في بيئة KVM
</h2>

<p>
	لا تقتصر إمكانيات التثبيت عبر الشبكة على الوسائط الموجودة على خواديم تشارك ملفات، بل يمكن استخدام خواديم أخرى مثل خواديم الوِب (Apache أو Nginx على سبيل المثال). سنأخذ في هذه الفقرة مثالا لإنشاء آلة افتراضية عبر الأداة <code>virt-manager</code> وتثبيت نظام تشغيل ضيف عن طريق وسيط تثبيت موجود على خادوم وِب.
</p>

<p>
	راجع درس <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AD%D8%B2%D9%85-mysql-%D8%8Capache-%D8%8Clinux-lamp-%D9%88-php-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r27/" rel="">كيف تثبت حزم MySQL ،Apache ،Linux :LAMP و PHP على أوبنتو 14.04</a> للمزيد عن تفاصيل تثبيت خادوم وِب Apache؛ أو مقال <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AD%D8%B2%D9%85-mysql-%D8%8Cnginx-%D8%8Clinux-lemp-%D9%88php-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r29/" rel="">كيف تثبت حزم MySQL ،nginx ،Linux :LEMP وPHP على أوبنتو 14.04 </a> إن كنت تفضّل خادوم Nginx. يمكن الاكتفاء - لأغراض هذا الدرس - بالجزء الأول من أحد المقالين المذكوريْن سابقا (تثبيت Apache أو Nginx دون بقية الحزم).
</p>

<p>
	لا يختلف تثبيت النظام الضّيف انطلاقا من وسيط تثبيت على خادوم وِب عن التثبيت عبر خادوم تشارك ملفات سوى في الخطوة الثانية عند تحديد العنوان. في حالة خادوم الوِب يُحدّد العنوان على النحو التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_9146_28">
http://192.168.122.1/ubuntu-14.04
</pre>

<p style="text-align: center;">
	<img alt="03_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19504" data-unique="2ybmvqkoj" src="https://academy.hsoub.com/uploads/monthly_2016_10/03_new_vm.png.afe67082e919cd207aeb75fdd66429a6.png"></p>

<p>
	رأينا في هذا الدرس والدرس السابق كيفية استخدام الأداة الرسومية <code>virt-manager</code> لإنشاء آلات افتراضيّة في بيئة تستخدم KVM للحوسبة الافتراضية؛ سنرى في الدرس الموالي كيفية إدارة الأقراص الافتراضية في هذه البيئة.
</p>

<p>
	ترجمة - بتصرّف لمقال <a href="http://www.tecmint.com/multiple-virtual-machine-installation-using-network-install-kvm/" rel="external nofollow">How to Deploy Multiple Virtual Machines using Network Install (HTTP, FTP and NFS) under KVM Environment – Part 2</a> لصاحبه Mohammad Dosoukey.
</p>
]]></description><guid isPermaLink="false">287</guid><pubDate>Sun, 15 Jan 2017 11:11:00 +0000</pubDate></item><item><title>&#x62A;&#x62B;&#x628;&#x64A;&#x62A; KVM &#x648;&#x625;&#x646;&#x634;&#x627;&#x621; &#x622;&#x644;&#x627;&#x62A; &#x627;&#x641;&#x62A;&#x631;&#x627;&#x636;&#x64A;&#x629; Virtual machines &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645;&#x647; &#x639;&#x644;&#x649; &#x623;&#x648;&#x628;&#x648;&#x646;&#x62A;&#x648;</title><link>https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-kvm-%D9%88%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A2%D9%84%D8%A7%D8%AA-%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%D8%A9-virtual-machines-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-r286/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_01/586b8bc55cbf1_kvm-ubuntu.png.4d93b451aca86b2a229c167290e13495.png" /></p>

<p>
	تقدّم تقنية KVM (اختصار Kernel-based Virtual Machine؛ الأجهزة الافتراضيّة المعتمدة على نواة لينكس) آلية لتشغيل الحوسبة الافتراضيّة (التخيّليّة أو الوهميّة) Virtualization على الأنظمة العاملة بلينكس. تمكّن هذه الآلية - التي تتوفّر على هيئة وحدة Module في نواة لينكس منذ الإصدار 2.6.20 - من استخدام أنظمة تشغيل مستقلّة ومنفصلة في وقت واحد على نفس العتاد Hardware. يتولّى نظامٌ يُعرَف بالمضيف Host تشغيل العتاد Hardware عن طريق برنامج يُعرَف بالمراقِب Hypervisor. يوفّر المراقب موارد (معالج، ذاكرة عشوائية، أجهزة طرفية وغيرها) للآلات الافتراضيّة. يُسمّى النظام الذي يُشغّل الآلة الافتراضيّة بالنظام الضيف Guest.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="20574" data-unique="dwrkeg6b1" src="https://academy.hsoub.com/uploads/monthly_2017_01/586b8bdde79cd_kvm-ubuntu.png.091c16b166b000f5fcad7fa419d7c1e5.png" style="" alt="kvm-ubuntu .png"></p>

<p>
	يقدّم KVM الميزات التاليّة:
</p>

<ul>
<li>
		التعهّد الزائد Over-commiting: يعني تخصيص موارد افتراضيّة (المعالجات والذاكرة العشوائية) أكثر من تلك التي يوفّرها العتاد.
	</li>
	<li>
		التموين السريع Thin provisionning: يسمح بالتوزيع المرن للمساحة التخزينية المتوفّرة والبحث عن أمثل طريقة لمشاركتها بين الآلات الافتراضية.
	</li>
	<li>
		تحجيم الإدخال/الإخراج من القرص Disk I/O throttling: يوفّر إمكانية تعريف حد لطلبات الإدخال والإخراج بالنسبة لكل آلة افتراضيّة.
	</li>
	<li>
		إمكانيّة زيادة قدرات المعالجة الخاصّة بالآلات الافتراضية حسب الطّلب دون الحاجة لإيقافها عن العمل.
	</li>
</ul>
<p>
	يتطرّق هذا المقال، الأوّل في سلسلة من أربعة أجزاء، لكيفية استخدام KVM والأدوات التي يوفّرها على توزيعة Ubuntu 16.04. تشترك توزيعات لينكس عموما في الخطوط العريضة، وكثير من الخطوات الواردة في هذه السلسلة.
</p>

<h2 id="المتطلبات">
	المتطلّبات
</h2>

<p>
	يجب أن تكون لدى العتاد الذي يعمل عليه النظام المُضيف القدرةُ على تنفيذ طلبات المُراقب عن طريق ما يُعرَف بامتدادات العتاد الخاصّة بالحوسبة الافتراضية Hardware virtualization extensions؛ وهو ما توفّره أغلب الحواسيب الحديثة. يمكّن الأمر <code>kvm-ok</code> من التأكد من جاهزيّة جهازك لاستخدام KVM:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_4028_7">
$ kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used</pre>

<p>
	يظهر من نتيجة الأمر أعلاه أن الجهاز قادر على استخدام التقنيّة. تأكّد، إن كانت النتيجة مخالفة، من أن امتدادات العتاد موجودة ومفعّلة في محمّل الإقلاع BIOS (أو UEFI) الخاص بجهازك.
</p>

<h2 id="تثبيت-أدوات-kvm-ونشر-الآلات-الافتراضية">
	تثبيت أدوات KVM ونشر الآلات الافتراضية
</h2>

<p>
	سنحتاج لبضعة حزم قبل أن يمكننا البدء في إنشاء آلات افتراضية باستخدام KVM. يُثبّت الأمر التالي هذه الحزم:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_4028_9">
$ sudo apt install qemu-kvm libvirt-bin bridge-utils virt-manager
</pre>

<ul>
<li>
		<p>
			تعمل حزمة أدوات <code>kvm-qemu</code> على تشغيل وحدة KVM في النواة لتنفيذ الشفرة البرمجية الخاصّة بالآلة الافتراضية. كما أن هذه الأدوات تحجز الذاكرة العشوائية والموارد التي تحتاجها الآلات الافتراضيّة للعمل؛ زيادة على كونها تعمل على محاكاة عمل الأجهزة الطرفية Peripherals الملموسة التي يتوفّر عليها النظام المُضيف من أجل إتاحة أجهزة طرفية افتراضية للنظام الضيف.
		</p>
	</li>
	<li>
		<p>
			تتيح الحزمة <code>libvirt-bin</code> مجموعة من الأدوات للتخاطب مع قدرات الحوسبة الافتراضية التي يتوفّر عليها الجهاز المضيف. نذكر مثلا الأداة <code>virsh</code> التي يمكن من خلالها إنشاء آلات افتراضية، تعليقها (توقيف مؤقّت) أو إيقافها عن العمل.
		</p>
	</li>
	<li>
		تحوي الحزمة <code>bridge-utils</code> الأدوات الضرورية لإنشاء أجهزة طرفية تعمل جسورا Bridge بين واجهات شبكة عدّة، ولإدارة هذه الأجهزة. من المهمّ توفّر هذه الميزة حتى يمكننا ضبط شبكة حواسيب تشمل الآلات الافتراضية.
	</li>
	<li>
		توفّر حزمة <code>virt-manage</code> واجهة رسومية لإدارة الآلات الافتراضية.
	</li>
</ul>
<p>
	الخطوة التاليّة هي إضافة المستخدم الحالي إلى مجموعة المستخدمين <code>libvirtd</code> حتى يمكنه استخدام الآلات الافتراضيّة التي ننشئها عن طريق KVM؛ إذ لا تُتاح هذه الوظيفة لغير أعضاء هذه المجموعة والحساب الجذر:
</p>

<pre>
 </pre>

<pre class="ipsCode" id="ips_uid_4028_11">
$ sudo adduser zeine77 libvirtd
</pre>

<p>
	نطلُب، من أجل التأكد من أن كل شيء على ما يُرام، سردَ الآلات الافتراضية المتوفّرة؛ وذلك باستخدام الأمر <code>virsh</code> على النحو التالي:
</p>

<pre class="ipsCode" id="ips_uid_4028_13">
$ virsh -c qemu:///system list
Id    Name                           State
----------------------------------------------------</pre>

<p>
	لا توجد آلات افتراضية لحد الساعة، لذا لن تظهر معلومات عن هذه الآلات؛ وسيكتفي الأمر بعرض أسماء أعمدة (المعرّف <code>Id</code>، الاسم <code>Name</code> والحالة <code>State</code>) تصف معلومات تتعلّق بالآلات الافتراضية. تشير هذه النتيجة إلى أننا مستعدون الآن للبدء في استخدام KVM.
</p>

<h2 id="إنشاء-آلات-افتراضية-باستخدام-kvm">
	إنشاء آلات افتراضية باستخدام KVM
</h2>

<p>
	سنستخدم في هذا الجزء من المقال الأداة <code>virt-manager</code> للتخاطب مع KVM من أجل إنشاء آلات افتراضية. يمكن تشغيل <code>virt-manager</code> من قوائم سطح المكتب الذي تستخدمه (Gnome، KDE أو غيرهما) أو بتنفيذ الأمر <code>virt-manager</code> في سطر الأوامر. تظهر النافذة التاليّة بعد تشغيل الأداة.
</p>

<p style="text-align: center;">
	<img alt="01_virt-manager.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19419" data-unique="zj2pqshhd" src="https://academy.hsoub.com/uploads/monthly_2016_10/01_virt-manager.png.7c46c96a4957ff30d239e9644dd761bf.png"></p>

<p>
	يظهر في واجهة البرنامج أنه متّصل بمضيف محلي يستخدم المُراقب QEMU/KVM. يمكن من هذه الواجهة الاتّصال بمضيفات Hosts بعيدة (توجد على أجهزة مغايرة للجهاز الذي تعمل عليه الأداة <code>virt-manager</code>)، وذلك عن طريق القائمة <strong>…File -&gt; Add Connection</strong> ثم تحديد الخانة <strong>Connect to remote host</strong> وذكر البيانات المطلوبة.
</p>

<p>
	ننقر على زر <strong>Create a new virtual machine</strong> في واجهة <code>virt-manager</code> لإنشاء آلة افتراضية جديدة.
</p>

<p style="text-align: center;">
	<img alt="02_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19420" data-unique="6qptmu4l6" src="https://academy.hsoub.com/uploads/monthly_2016_10/02_create_new_vm.png.1fdda6554d590bc5c6b4dec118be3f78.png"></p>

<p>
	تظهر نافذة جديدة تطلُب تحديد طريقة لتثبيت نظام التشغيل الضّيف على الآلة الافتراضية.
</p>

<p style="text-align: center;">
	<img alt="03_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19421" data-unique="60186rw40" src="https://academy.hsoub.com/uploads/monthly_2016_10/03_create_new_vm.png.7472000bfe99b26a1abd3e9d9a7f587e.png"></p>

<p>
	توجد أكثر من طريقة كما يظهر في لقطة الشاشة أعلاه. سنحدّد خيار <strong>Local install media</strong> (وسيط تثبيت محليّ). تظهر النافذة التاليّة.
</p>

<p style="text-align: center;">
	<img alt="04_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19422" data-unique="7b0vbis69" src="https://academy.hsoub.com/uploads/monthly_2016_10/04_create_new_vm.png.05f6af3453e55fddf19247c9aaae59b2.png"></p>

<p>
	يمكن عبر الواجهة الظاهرة في الصورة أعلاه الاختيار بين قرص مُدمَج (CD أو DVD) أو ملفّ ISO. سنحدّد الخيار الثاني (ملف ISO) وننقر على الزّر <strong>Browse</strong>. تظهر النافذة التالية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19423" href="https://academy.hsoub.com/uploads/monthly_2016_10/05_create_new_vm.png.1423f9d75c8a8688c9cd13f66734a46d.png" rel=""><img alt="05_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19423" data-unique="fpkj8hp1f" src="https://academy.hsoub.com/uploads/monthly_2016_10/05_create_new_vm.thumb.png.006938900539ecd20090f545cc17dd57.png"></a>
</p>

<p>
	نستطيع عبر هذه النافذة إنشاء مساحة تخزين Storage volume افتراضية لاستخدامها مع الآلة؛ إلا أننا لن نفعل ذلك الآن وسننقر على الزّر <strong>Browse Local</strong> لتحديد المسار Path الذي يوجد عليه ملفّ ISO. يعود البرنامج بعد تحديد المسار إلى واجهة الاختيار الخاصة بوسيط التثبيت.
</p>

<p style="text-align: center;">
	<img alt="06_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19424" data-unique="cgxvgid1g" src="https://academy.hsoub.com/uploads/monthly_2016_10/06_create_new_vm.png.47a326c48364e15fff35eeb11488a7fc.png"></p>

<p>
	نلاحظ أن البرنامج تعرّف تلقائيا على نوعية نظام التشغيل وإصداره اعتمادا على اسم وسيط التثبيت.
</p>

<p>
	ثم يطلب منا البرنامج ضبط إعدادات المعالج والذاكرة العشوائية الخاصّين بالآلة الافتراضيّة.
</p>

<p style="text-align: center;">
	<img alt="07_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19425" data-unique="9nkzlkulv" src="https://academy.hsoub.com/uploads/monthly_2016_10/07_create_new_vm.png.4414d4835eeaf720fa529e438f8e9884.png"></p>

<p>
	نختار القيم المناسبة اعتمادا على العتاد المتوفّر على المُضيف ثم ننتقل لإعدادات التخزين.
</p>

<p style="text-align: center;">
	<img alt="08_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19426" data-unique="of0i8all8" src="https://academy.hsoub.com/uploads/monthly_2016_10/08_create_new_vm.png.7c60375e1e5098f342ec45698dbf31c7.png"></p>

<p>
	يمكن تحديد أحد خيارين؛ إما إنشاء مساحة تخزين افتراضية جديدة أو اختيار مساحة تخزين افتراضية موجودة سلفا. بما أننا لم نضبُط مساحة تخزين قبلًا فسنحدّد الخيار الأول.
</p>

<p>
	ثم ننتقل للخطوة الأخيرة وهي تحديد اسم للآلة الافتراضية.
</p>

<p style="text-align: center;">
	<img alt="09_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19427" data-unique="zkgrsph16" src="https://academy.hsoub.com/uploads/monthly_2016_10/09_create_new_vm.png.574d6fbcbf7a0b6d89ac3ff22deb9fe6.png"></p>

<p>
	إن أردت تخصيص عمليّة التثبيت فبإمكانك تحديد الخيار <strong>Customize configuration before install</strong> (تخصيص الإعدادات قبل التثبيت). ثم ننقر على زر <strong>Finish</strong>. تبدأ الآلة الافتراضية بالعمل مباشرة وتظهر في واجهة برنامج <code>virt-manager</code> شاشةُ التثبيت الخاصّة بنظام التشغيل الضيف على الآلة الافتراضية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="19428" href="https://academy.hsoub.com/uploads/monthly_2016_10/10_create_new_vm.png.8d4fd66dad7d3467356ea1263ccc2a4c.png" rel=""><img alt="10_create_new_vm.png" class="ipsImage ipsImage_thumbnailed" data-fileid="19428" data-unique="dud624o7c" src="https://academy.hsoub.com/uploads/monthly_2016_10/10_create_new_vm.thumb.png.ed641aa3699068afaa390d5d25c61ef9.png"></a>
</p>

<p>
	توجد في واجهة <code>virt-manager</code> أزرار للتحكّم في الآلة الافتراضية: إعادة التشغيل Reboot، الإيقاف Shut Down، فرض إعادة التعيين Force reset، فرض الإيقاف Force off (يشبه فصل حاسوب عن الطاقة دون إيقاف نظام التشغيل) وحفظ حالة الآلة Save. كما يمكن عن طريق زرّ Open فتح نافذة خاصّة للآلة الافتراضية يمكن عبرها أخذ لقطات سريعة Snapshots. تخزّن اللقطات السريعة جميع البيانات الموجودة على الآلة ويمكن الرجوع إلى هذه اللقطات في حالات مثل حدوث مشكل مع الآلة الافتراضية، توقفها عن العمل أو لإنشاء آلة افتراضية مطابقة لها تماما.
</p>

<p>
	ترجمة - بتصرّف - لمقال <a href="http://www.tecmint.com/install-and-configure-kvm-in-linux/" rel="external nofollow">How to Create Virtual Machines in Linux Using KVM (Kernel-based Virtual Machine) – Part 1</a> لصاحبه Mohammad Dosoukey.
</p>
]]></description><guid isPermaLink="false">286</guid><pubDate>Mon, 02 Jan 2017 00:01:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x62B;&#x628;&#x64A;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3 &#x648;&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x628;&#x64A;&#x626;&#x629; &#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; &#x641;&#x64A; &#x62A;&#x648;&#x632;&#x64A;&#x639;&#x629; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648; 16.04</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A9-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1604-r304/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/install-python.png.db28e76a7ae39298640d8d9acfa6d972.png" /></p>

<h2 id="كيفية-تثبيت-بايثون-3-وإعداد-بيئة-برمجية-في-توزيعة-أوبنتو-1604">
	تمهيد
</h2>

<p>
	سنشرح في هذا الدرس كيفية إعداد بيئة برمجية محليّة للغة بايثون 3 في توزيعة أوبنتو 16.04 أو دبيان 8.<br>
	بايثون هي لغةٌ سهلة القراءة للغاية ومتنوعة ومتعددة الاستخدامات، واسمها مستوحى من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وإعدادها بسيطٌ، وطريقة كتابتها مباشرة وتعطيك تقريرًا مباشرًا عند حدوث أخطاء، وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعتَبَر أنَّه مستقبل بايثون.
</p>

<p style="text-align: center;">
	<img alt="install-python.png" class="ipsImage ipsImage_thumbnailed" data-fileid="21836" data-unique="8u7yoqslq" src="https://academy.hsoub.com/uploads/monthly_2017_02/install-python.png.7e229cc6bd45c8f576453f2a2632f742.png" style=""></p>

<p>
	سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 على نظام لينكس المحلي عندك وذلك عبر سطر الأوامر، وصحيحٌ أنَّ هذا الدرس يشرح عملية التثبيت لتوزيعة أوبنتو 16.04 أو دبيان 8، إلا أنَّ المفاهيم الأساسية فيه تنطبق على أيّة توزيعة أخرى.
</p>

<h2 id="المتطلبات-المسبقة">
	المتطلبات المسبقة
</h2>

<p>
	يجب أن يكون لديك حاسوبٌ يعمل بتوزيعة أوبنتو 16.04 أو دبيان 8 (أو أيّ إصدار آخر من دبيان)، وأن تكون لديك امتيازات إدارية على النظام، بالإضافة إلى اتصالٍ بالإنترنت.
</p>

<h2 id="الخطوة-الأولى-إعداد-بايثون-3">
	الخطوة الأولى: إعداد بايثون 3
</h2>

<p>
	سنُثبِّت ونضبط بايثون عبر سطر الأوامر، والذي هو طريقةٌ غيرُ رسوميةٍ للتعامل مع الحاسوب، فبدلًا من الضغط على الأزرار فستكتب نصًا وتعطيه للحاسوب لينفذه وسيُظهِر لك ناتجًا نصيًا أيضًا. يمكن أن يساعدك سطر الأوامر على تعديل أو أتمتة مختلف المهام التي تنجزها على الحاسوب يوميًا، وهو أداةٌ أساسيةٌ لمطوري البرمجيات، وهنالك الكثير من الأوامر التي عليك تعلمها لكي تتمكن من الاستفادة منه. هنالك مقالات في أكاديمية حسوب (كدرس <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%B7%D8%B1%D9%81%D9%8A%D9%91%D8%A9-%D9%84%D9%8A%D9%86%D9%83%D8%B3-linux-terminal-r18/" rel="">مدخل إلى طرفيّة لينكس Linux Terminal</a>) ستعلمك أساسيات سطر الأوامر، وهنالك كتاب «<a href="http://sourceforge.net/projects/omlx/files/open%20books/TLCL/The_Linux_Command_Line-arabic-14.07.pdf/download" rel="external nofollow">سطر أوامر لينكس</a>» الذي يُعتَبر مرجعًا تفصيلًا لطريقة التعامل مع سطر الأوامر.<br>
	ستجد تطبيق «Terminal» (البرنامج الذي تستعمله للوصول إلى سطر الأوامر) بالضغط على أيقونة Dash في الزاوية العليا اليسرى من الشاشة ثم كتابة «terminal» في شريط البحث، ثم الضغط على أيقونة التطبيق التي ستظهر بعدئذٍ. يمكنك بشكلٍ بديلٍ أن تضغط على Ctrl+Alt+T في لوحة المفاتيح بنفس الوقت لتشغيل تطبيق Terminal.
</p>

<p style="text-align: center;">
	<img alt="1-UbuntuSetUp.png" class="ipsImage ipsImage_thumbnailed" data-fileid="21834" data-unique="8cz5dhw5w" src="https://academy.hsoub.com/uploads/monthly_2017_02/1-UbuntuSetUp.png.0a2eb91c548d5121d13e8bfe8e9207a3.png" style=""></p>

<p>
	أما على دبيان 8 فيمكنك فتح القائمة الموجودة أيضًا في الزاوية العليا اليسرى من الشاشة ثم البحث عن «terminal» في شريط البحث، ثم النقر على أيقونة التطبيق. يمكنك أيضًا أن تضغط على Ctrl+Alt+T في لوحة المفاتيح بنفس الوقت لتشغيل تطبيق Terminal.
</p>

<p style="text-align: center;">
	<img alt="2-DebianSetUp.png" class="ipsImage ipsImage_thumbnailed" data-fileid="21835" data-unique="qdon0xuo5" src="https://academy.hsoub.com/uploads/monthly_2017_02/2-DebianSetUp.png.a63370cf7657c1ead129d70c14ef34b6.png" style=""></p>

<p>
	تأتي توزيعات أوبنتو 16.04 ودبيان 8 وإصدارات دبيان الأخرى مثبتةً مسبقًا مع بايثون 3 وبايثون 2. للتأكد أنَّك تملك آخر الإصدارات منها فحدِّث نظامك باستخدام <code>apt-get</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo apt</span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">get</span></span><span class="pln"> update
sudo apt</span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">get</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">y</span></span><span class="pln"> upgrade</span></code></pre>

<p>
	الخيار <code>‎-y</code> يعني أنَّك توافق على تثبيت جميع الحزم القابلة للتحديث، لكن قد تحتاج إلى تأكيد ذلك عند تحديث النظام وذلك اعتمادًا على الحزم التي ستُحدَّث ونسخة نظامك.<br>
	بعد إكمال العملية، يمكننا التحقق من إصدار بايثون 3 المُثبّت في النظام بكتابة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">python3 </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">V</span></span></code></pre>

<p>
	ستحصل على مخرجات في نافذة الطرفية والتي ستريك ما هو إصدار بايثون المثبّت. قد يختلف الرقم بناءً على النسخة المثبتة في توزيعتك، لكن يجب أن يكون شبيهًا بما يلي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs "><span class="typ">Python</span><span class="pln"> </span><span class="lit">3.5</span><span class="pun">.</span><span class="lit">2</span></code></pre>

<p>
	لإدارة الحزم البرمجية الخاصة ببايثون، فثبّت <code>pip</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo apt</span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">get</span></span><span class="pln"> install </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">y</span></span><span class="pln"> python3</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">pip</span></span></code></pre>

<p>
	الأداة <code>pip</code> هي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تثبيت حزم بايثون بكتابة الأمر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs cmake"><span class="pln">pip3 </span><span class="hljs-keyword"><span class="pln">install</span></span><span class="pln"> package_name</span></code></pre>

<p>
	حيث عليك وضع اسم الحزمة أو المكتبة التابعة لبايثون مكان <code>package_name</code> مثل Django لتطوير الويب أو NumPy لإجراء حسابات علمية. لذا إن شئتَ تنزيل NumPy فيمكنك تنفيذ الأمر <code>pip3 install numpy</code>.<br>
	بعد أن انتهينا من ضبط بايثون وتثبيت pip، فيمكننا الآن إنشاء «بيئة وهمية» (virtual environment) لمشاريعنا.
</p>

<h2 id="الخطوة-الثانية-إعداد-بيئة-وهمية">
	الخطوة الثانية: إعداد بيئة وهمية
</h2>

<p>
	تُمكِّنك البيئات الوهمية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه يملك مجموعة من الاعتماديات (dependencies) والتي لن تؤثِّر على غيره من المشاريع.<br>
	يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية.<br>
	يمكنك ضبط أيُّ عددٍ تشاء من البيئات الوهمية، وكل بيئة تُمثِّل مجلدًا في حاسوبك الذي فيه عددٌ من السكربتات.<br>
	علينا أولًا تثبيت وحدة (module) برمجية باسم <code>venv</code>، وهي جزءٌ من مكتبة بايثون3 القياسية، وذلك لكي نتمكن من استخدام الأمر <code>pyvenv</code> الذي سيُنشِئ البيئات الوهمية لنا. لنثبِّت <code>venv</code> على نظامنا بكتابة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo apt</span><span class="hljs-attribute"><span class="pun">-</span><span class="kwd">get</span></span><span class="pln"> install </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">y</span></span><span class="pln"> python3</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">venv</span></span></code></pre>

<p>
	سنتمكن الآن من إنشاء بيئات وهمية بعد إتمام التثبيت، لنختار ما هو المجلد الذي سنضع فيه بيئات بايثون، أو لننشِئ مجلدًا جديدًا باستخدام الأمر <code>mkdir</code> كما يلي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="pln">mkdir environments
</span><span class="hljs-built_in"><span class="pln">cd</span></span><span class="pln"> environments</span></code></pre>

<p>
	بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، فتستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر الآتي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs "><span class="pln">pyvenv my_env</span></code></pre>

<p>
	سيُنشِئ الأمر <code>pyvenv</code> مجلدًا جديدًا فيه بعض الملفات التي يمكننا عرضها باستخدام الأمر <code>ls</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs ruby"><span class="pln">ls my_env

bin </span><span class="hljs-keyword"><span class="pln">include</span></span><span class="pln"> lib lib64 pyvenv</span><span class="pun">.</span><span class="pln">cfg share</span></code></pre>

<p>
	تعمل هذه الملفات مع بعضها لضمان أنَّ مشاريعك معزولةٌ عن بقية النظام، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى حزمٍ معيّنة التي يحتاج لها. تتوافر أيضًا Python Wheels والتي هي صيغة بناء حزمٍ لبايثون والتي يمكن أن تُسرِّع من تطوير البرامج بتقليل عدد المرات التي تحتاج فيها إلى بناءٍ (compile) للمشروع، وهي موجودةٌ في مجلد <code>share</code> في توزيعة أوبنتو 16.04 لكنها ستكون في دبيان 8 في أحد مجلدات <code>lib</code> وليس في <code>share</code>.<br>
	عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر الآتي الذي سيُنفِّذ سكربت التفعيل:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">source</span></span><span class="pln"> my_env</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">activate</span></code></pre>

<p>
	يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها <code>my_env</code>، وقد يكون مظهر المِحَث مختلفًا في توزيعة دبيان، وذلك اعتمادًا على الإصدار المستخدم؛ لكن يجب أن تشاهد اسم البيئة بين قوسين في بداية السطر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs ruby"><span class="pun">(</span><span class="pln">my_env</span><span class="pun">)</span><span class="pln"> sammy</span><span class="hljs-variable"><span class="pln">@sammy</span></span><span class="hljs-symbol"><span class="pun">:~/</span><span class="pln">environments</span></span><span class="pln">$</span></code></pre>

<p>
	السابقة ستسمح لك بمعرفة أنَّ البيئة <code>my_env</code> مفعلة حاليًا، وهذا يعني أننا سنستخدم إعدادات وحزم هذه البيئة عند إنشائنا لمشاريع جديدة.<br>
	ملاحظة: يمكنك داخل البيئة الوهمية أن تستخدم الأمر <code>python</code> بدلًا من <code>python3</code> والأمر <code>pip</code> بدلًا من <code>pip3</code> إن شئتَ. أما إذا كنتَ ستستخدم بايثون 3 خارج البيئة الوهمية، فيجب عليك حينها استخدام <code>python3</code> و <code>pip3</code> حصرًا.<br>
	يجب أن تكون بيئتك الوهمية جاهزةً للاستخدام بعد اتباعك للخطوات السابقة.
</p>

<h2 id="الخطوة-الثالثة-إنشاء-برنامج-بسيط">
	الخطوة الثالثة: إنشاء برنامج بسيط
</h2>

<p>
	بعد أن أكملنا ضبط بيئتنا الوهمية، لننشِئ برنامجًا بسيطًا يعرض العبارة «Hello World!‎»، وبهذا سنتحقق من أنَّ البيئة تعمل عملًا صحيحًا، وستصبح طريقة إنشاء برامج بايثون مألوفةً لديك إن كنتَ وافدًا جديدًا على اللغة.<br>
	علينا أولًا تشغيل محرر ملفات نصية لإنشاء ملف جديد، وليكن المحرر <code>nano</code> الذي يعمل من سطر الأوامر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs ruby"><span class="pun">(</span><span class="pln">my_env</span><span class="pun">)</span><span class="pln"> sammy</span><span class="hljs-variable"><span class="pln">@sammy</span></span><span class="hljs-symbol"><span class="pun">:~/</span><span class="pln">environments</span></span><span class="hljs-variable"><span class="pln">$ </span></span><span class="pln">nano hello</span><span class="pun">.</span><span class="pln">py</span></code></pre>

<p>
	بعد فتح الملف في نافذة الطرفية، فاكتب البرنامج الخاص بنا:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs erlang"><span class="hljs-function"><span class="hljs-title"><span class="kwd">print</span></span><span class="hljs-params"><span class="pun">(</span><span class="hljs-string"><span class="str">"Hello, World!"</span></span><span class="pun">)</span></span></span></code></pre>

<p>
	أغلق محرر nano بالضغط على Ctrl+x ثم اضغط على y عندما يسألك عن حفظ الملف.<br>
	بعد أن يُغلَق محرر nano وتعود إلى سطر الأوامر، فحاول تشغيل البرنامج:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs ruby"><span class="pun">(</span><span class="pln">my_env</span><span class="pun">)</span><span class="pln"> sammy</span><span class="hljs-variable"><span class="pln">@sammy</span></span><span class="hljs-symbol"><span class="pun">:~/</span><span class="pln">environments</span></span><span class="hljs-variable"><span class="pln">$ </span></span><span class="pln">python hello</span><span class="pun">.</span><span class="pln">py</span></code></pre>

<p>
	سيؤدي برنامج <code>hello.py</code> الذي أنشأتَه إلى طباعة الناتج الآتي في الطرفية:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs erlang-repl"><span class="hljs-variable"><span class="typ">Hello</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="typ">World</span></span><span class="hljs-exclamation_mark"><span class="pun">!</span></span></code></pre>

<p>
	للخروج من البيئة، فاكتب الأمر <code>deactivate</code> وستعود إلى مجلدك الأصلي.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	تهانينا! لقد ضبطتَ الآن بيئة تطوير للغة بايثون 3 في جهازك الذي يعمل بتوزيعة أوبنتو أو دبيان، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق.<br>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-ubuntu-16-04" rel="external nofollow">How To Install Python 3 and Set Up a Local Programming Environment on Ubuntu 16.04</a> لصاحبته Lisa Tagliaferri
</p>
]]></description><guid isPermaLink="false">304</guid><pubDate>Sat, 24 Dec 2016 23:00:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x645;&#x635;&#x637;&#x644;&#x62D;&#x627;&#x62A; &#x648;&#x645;&#x641;&#x627;&#x647;&#x64A;&#x645; &#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x641;&#x64A; &#x644;&#x64A;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r301/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/5eeaf56b419a0_------.jpg.4b99995beb4ab328f8f215e9e1164c6a.jpg" /></p>

<p id="مدخل-إلى-مصطلحات-ومفاهيم-التخزين-في-لينكس">
	يملك لينُكس أنظمةً صلبةً وأدواتٍ عمليةً لإدارة الأجهزة والعتاد، بما في ذلك أجهزة التخزين. سنشرح في درسنا هذا كيفية تمثيل تلك الأجهزة في لينكس وكيف يمكن تحويل المساحات الخام إلى مساحاتٍ تخزينيةٍ قابلةٍ للاستخدام على الخواديم.
</p>

<p style="text-align: center;">
	 
</p>

<h2 id="ما-هو-التخزين-الكتلي">
	ما هو التخزين الكتلي؟
</h2>

<p>
	التخزين الكتلي (Block storage) هو اسمٌ آخر لما تدعوه نواة لينُكس بالجهاز الكتلي (block device). والجهاز الكتلي هو قطعةٌ من العتاد التي يمكن استعمالها لتخزين البيانات، مثل أقراص التخزين الصلبة الاعتيادية (HDD) أو أقراص التخزين ذات الحالة الثابتة (solid state drive أي SSD) أو وحدات الذاكرة الفلاشية (flash memory stick) …إلخ. تلك تسمى «أجهزةً كتليةً» لأنَّ النواة تتعامل مع العتاد على أنَّه كتلٌ ثابتةُ الحجم، أو قطعٌ من المساحة.<br>
	بشكلٍ أساسي، التخزين الكتلي هو ما نعتبر أنَّه التخزين الاعتيادي المتواجد في الحواسيب، والذي –بعد ضبطه وإعداده– سيعمل على أنَّه جزءٌ من شجرة نظام الملفات الحالية، وستتمكن من قراءة أو كتابة المعلومات منه وإليه بسلاسة.
</p>

<h2 id="ما-هي-الأقسام-في-الأقراص">
	ما هي الأقسام في الأقراص؟
</h2>

<p>
	الأقسام (partitions) هي طريقةٌ لتقسيم جهاز التخزين إلى وحدات قابلة للاستخدام أصغر حجمًا، إذ أنَّ القسم هو جزءٌ من جهاز التخزين الذي يمكن معاملته بطريقةٍ مشابهةٍ لطريقة التعامل مع القرص نفسه.<br>
	يسمح لك التقسيم بتجزئة المساحة المتوافرة لديك واستخدام كل قسمٍ لغرضٍ مختلف. وهذا يعطي المستخدمين الكثير من المرونة سامحًا لهم بتجزئة النظام لديهم لتحديثه بسهولة أو لتثبيت أكثر من نظام تشغيل أو لإنشاء مساحة تبديل (swap) أو لاستخدام أنظمة ملفات خاصة على تلك الأجزاء.<br>
	وصحيحٌ أنَّ الأقراص يمكن أن تُهيّئ (format) وتُستعمَل دون تقسيم، إلا أنَّ بعض أنظمة التشغيل تتوقع وجود «جدول أقسام» (partition table) حتى ولو كان هنالك قسمٌ وحيدٌ في القرص؛ لذا يُستحسَن ويُنصَح عمومًا إنشاء أقسام في الأجهزة الجديدة لضمان مرونة استخدامها مهما كانت الظروف.
</p>

<h3 id="mbr-أم-gpt">
	MBR أم GPT؟
</h3>

<p>
	من المهم عند تقسيم القرص معرفة ما هي «صيغة» التقسيم التي ستستعملها، وسينتهي بك المطاف بالاختيار بين MBR (اختصار للعبارة Master Boot Record) و GPT (اختصار للعبارة GUID Partition Table).<br>
	MBR هو نظام التقسيم التقليدي الذي بقي مُستخدَمًا طيلة 30 عامًا الماضية؛ ونتيجةً لعمره الطويل، فهو يعاني من بعض المحدوديات التي لها وقعٌ كبير. فمثلًا لا يمكننا استخدامه للأقراص التي حجمها التخزيني أكبر من 2 تيرابايت، ولا يمكن إنشاء أكثر من أربعة أقسام رئيسية (primary partitions)؛ ونتيجةً لذلك نضبط عادةً القسم الرابع على أنَّه «قسمٌ ممتد» (extended partition) الذي سيُنشَأ داخله «أقسامٌ منطقيةٌ» (logical partitions). وهذا يسمح لك بتجزئة آخر قسم لإنشاء أي عدد إضافي من الأقسام.<br>
	GPT على الجانب الآخر هو تخطيط حديث للتقسيم الذي يحاول حلّ بعضًا من المشكلات الموروثة من MBR، الأنظمة التي تستعمل GPT يمكن فيها إنشاء أي عددٍ نريده من الأقسام، لكن هذا محدودٌ عادةً بالقيود المفروضة من نظام التشغيل نفسه. إضافةً إلى ما سبق، لا تعاني أقراص GPT من محدوديات في حجم القرص، ومعلوماتُ جدولِ الأقسامِ متوافرةٌ في مواضعَ عدَّة مما يحميها من التلف. يمكن أيضًا كتابة سجل «protective MBR» الذي يخبر الأدوات التي تتعامل مع أقراص MBR فقط أنَّ القرص قيد الاستخدام حاليًا.<br>
	من الأفضل في أغلبية الحالات اختيار GPT ما لم يمنعك نظام تشغيلك أو الأدوات التي ستستعملها من ذلك.
</p>

<h2 id="التهيئة-وأنظمة-الملفات">
	التهيئة وأنظمة الملفات
</h2>

<p>
	صحيحٌ أنَّ نواة لينكس يمكنها التعرف على الأقراص الخام (raw disks) إلا أنَّ القرص لا يمكن أن يُستعمل كما هو؛ وإنما يجب تهيئته (format) قبل استعماله. التهيئة هي عملية كتابة نظام ملفات إلى القرص وتجهيزه لإجراء عمليات لها علاقة بالملفات. أما نظام الملفات (filesystem) فهو النظام الذي يُنظِّم البيانات ويتحكم بكيفية كتابة المعلومات إلى القرص والحصول على المعلومات من القرص؛ فبدون نظام الملفات لن تتمكن من استخدام جهاز التخزين لأيّة عمليات لها علاقة بالملفات.<br>
	هنالك الكثير من صيغ أنظمة الملفات المختلفة، والتي تتباين فيما بينها بامتلاكها لميزاتٍ مختلفة، بما في ذلك دعمُ أنظمة التشغيل. لكن بشكلٍ أساسي، تمنح جميع أنظمة الملفات للمستخدم تمثيلًا مألوفًا للقرص، لكن الميزات التي يدعمها كل نظام ملفات وآلية سماحه للمستخدم بالتعامل وإجراء عمليات على القسم مختلفةٌ تمامًا.<br>
	بعضٌ من أشهر أنظمة الملفات المتاحة للينكس:
</p>

<ul>
<li>
		Ext4: أشهر نظام ملفاتٍ افتراضيٍ في لينكس هو Ext4 (اختصار للعبارة the fourth version of the extended filesystem) وهو نظام ملفات ذو سجل (journaled)، ومتوافق مع الأنظمة القديمة، ومستقر للغاية، ومدعومٌ دعمًا واسعًا وتتوافر له أدواتٌ كثيرة؛ وهو خيارٌ جيدٌ إن لم تكن لديك احتياجاتٌ خاصة.
	</li>
	<li>
		XFS: نظام ملفات XFS متخصصٌ بموضوع الأداء وبالملفات كبيرة الحجم، وستتم تهيئته بسرعة وأداؤه جيد عند التعامل مع الملفات الكبيرة ومع الأقراص الضخمة. ولديه ميزة أخذ snapshot من نظام الملفات. يعتمدXFS على تسجيل البيانات الوصفية (metadata journaling) فقط والذي يختلف عن تسجيل البيانات الوصفية والبيانات نفسها؛ وهذا يؤدي إلى سرعةٍ في الأداء، لكن قد يؤدي في الوقت نفسه إلى حدوث تلفٍ في البيانات في حال حدوث فقدان غير متوقع للطاقة الكهربائية.
	</li>
	<li>
		Btrfs: نظام ملفات Btrfs هو نظامٌ حديثٌ له ميزاتٌ كثيرة وهو من نمط copy-on-write بدل كونه journaled، هذه المعمارية تسمح لبعض وظائف إدارة الحجوم (volume management) بأن تُدمَج مع طبقة نظام الملفات، بما في ذلك snapshots، والنسخ (cloning)، والحجوم (volumes) …إلخ. لكن نظام ملفات Btrfs ما يزال يواجه مشاكل عند التعامل مع الأقراص الممتلئة. هنالك بعض الجدال الدائر حول جاهزية نظام الملفات هذا لاستعماله في بيئات العمل الإنتاجية، وينتظر الكثير من مدراء الأنظمة أن يصل Btrfs إلى درجةً أكبر من الدعم والانتشار.
	</li>
	<li>
		ZFS: هو نظام ملفاتٍ من نمط copy-on-write وفيه مدير حجوم (volume manager) بمجموعة متينةٍ ومستقرةٍ من الميزات. يحتوي أيضًا على ميزاتٍ ممتازةٍ لضمان سلامة البيانات المُخزَّنة عليه، ويمكنه التعامل مع أقسام ذات مساحات تخزينية كبيرة، وفيه ميزات إدارة الحجوم التقليدية مثل snapshotting و cloning، ويمكن فيه تنظيم الحجوم (volumes) إلى مصفوفة RAID أو مصفوفات شبيهة بمصفوفات RAID لغرض إنشاء نظام تخزيني مستقر وذي أداءٍ عالٍ. أما عن وضع دعم ZFS في لينكس، فيجدر بالذكر أنَّ له تاريخٌ جدليٌ نتيجةً لمخاوف من رخصة استعماله. أصبحت توزيعة أوبنتو توفِّر وحدة ثنائية (binary module) من وحدات النواة للتعامل معه، وتضع توزيعة دبيان الشيفرة المصدرية له في مستودعاتها، لكن لم يُحدَّد دعمه في بقية التوزيعات بعد.
	</li>
</ul>
<h2 id="كيف-يدير-لينكس-أقراص-التخزين">
	كيف يُدير لينُكس أقراص التخزين
</h2>

<h3 id="ملفات-التخزين-الموجودة-في-dev">
	ملفات التخزين الموجودة في ‎/dev
</h3>

<p>
	من المعروف أنَّ كل شيء في لينُكس (تقريبًا) يُمثَّل بملف؛ بما في ذلك الأجهزة العتادية مثل أجهزة التخزين والتي تُمثَّل في النظام كملفات في مجلد <code>‎/dev</code>، وعمومًا تبدأ أسماء الملفات التي تُمثِّل أجهزة التخزين بالحرفين <code>sd</code> أو <code>hd</code> متبوعَين بحرفٍ آخر؛ فمثلًا: أوّل قرص تخزين على الخادوم يكون اسمه شبيهًا بالاسم <code>‎/dev/sda</code>.<br>
	تملك الأقسام على تلك الأجهزة ملفاتٍ هي الأخرى ضمن مجلد <code>‎/dev</code>، ممثلةً بإضافة رقم القسم إلى نهاية اسم الجهاز، فعلى سبيل المثال، أوّل قسمٍ في القرص المذكور في المثال السابق سيكون على الشكل <code>‎/dev/sda1</code>.<br>
	وعلى الرغم من أنَّ ملفات الأجهزة <code>‎/dev/sd*‎</code> و <code>‎/dev/hd*‎</code> هي الطريقة التقليدية للإشارة إلى الأجهزة والأقسام، إلا أنَّ هنالك جانبٌ سلبيٌ لاستخدام تلك المسارات، إذ أنَّ نواة لينكس تُقرِّر ما هو الجهاز الذي سيحصل على الاسم الفلاني عند كل إقلاعٍ للنظام، لذا قد يودي ذلك إلى تضاربات حيث تتغير أسماء عقد الأجهزة.<br>
	حلٌ التفافيٌ على هذه المشكلة هو احتواء المجلد <code>‎/dev/disk</code> على مجلدات فرعية تَنظُمُ الأقراص والأقسام بطرائق ثابتةٍ لا تتغير؛ وتلك المجلدات تحتوي على وصلاتٍ رمزيةٍ (symbolic links) التي تُنشَأ عند الإقلاع لتشير إلى ملفات <code>‎/dev/[sh]da*‎</code> الصحيحة. تُسمى تلك الوصلات وفقًا لنوع طريقة التنظيم والموضَّحة باسم المجلد (على سبيل المثال، ستسمى الوصلات حسب «لُصيقة» [label] القسم في مجلد <code>‎/dev/disk/by-partlabel</code>). ستُشير تلك الوصلات دومًا إلى الأجهزة الصحيحة، لذا يمكننا استخدامها كمُعرِّفات ثابتة لأجهزة التخزين.<br>
	بعض (أو جميع) المجلدات الآتية موجودةٌ ضمن مجلد <code>‎/dev/disk</code>:
</p>

<ul>
<li>
		<code>by-label</code>: أغلبية أنظمة الملفات لها آلية لإعطاء لُصيقة سامحةً بإسناد أسماء يُحدِّدها المستخدم إلى القرص أو القسم؛ يحتوي هذا المجلد على وصلاتٍ مسماةٍ تِبعًا للُصيقات التي كتبها المستخدم.
	</li>
	<li>
		<code>by-uuid</code>: المُعرِّفات العالمية الفريدة (اختصارًا UUIDs) هي سلسلةٌ طويلةٌ فريدةٌ من الحروف والأرقام التي يمكن أن تُستعمَل كمُعرِّف لوسيط التخزين. تلك المُعرِّفات ليست سهلة القراءة من البشر، لكنها فريدة، وستبقى ثابتةً حتى لو بدَّلنا الخادوم أو النظام؛ لذا من الأفضل استخدام مُعرِّفات UUID للإشارة إلى أجهزة التخزين التي قد تُنقَل بين الأنظمة بين الحين والآخر، لأنَّ من غير المحتمل أن يحدث تضاربٌ في الأسماء.
	</li>
	<li>
		<code>by-partlabel</code> و <code>by-partuuid</code>: توفِّر جداول GPT لافتاتٍ ومعرِّفات UUID خاصة بها، والتي يمكن أن تُستعمَل أيضًا بغرض تمييز الأقسام، وتعمَل بنفس طريقة عَمَل المجلدين السابقين، إلا أنَّها تستعمل مُعرِّفات خاصة بجداول GPT.
	</li>
	<li>
		<code>by-id</code>: يحتوي هذا المجلد على وصلات مُولَّدةٌ أسماؤها من الرقم التسلسلي لجهاز التخزين وللجهاز الموصول إليه، وتلك الأسماء غير ثابتة تمامًا، لأنَّ طريقة وصل الجهاز إلى النظام قد تُغيّر من اسم وصلات المجلد <code>by-id</code>.
	</li>
	<li>
		<code>by-path</code>: وكما في مجلد <code>by-id</code>، تعتمد الوصلات الموجودة في هذا المجلد على أجهزة التخزين الموصول إلى النظام نفسه، وتُبنى تلك الوصلات اعتمادًا على طريقة تمثيل العتاد الذي يُستعمَل للوصول إلى وسيط التخزين في نظام التشغيل. وللوصلات الموجودة في هذا المجلد نفس الإشكاليات التي تواجهها تلك الموجودة في <code>by-id</code> لأنَّ وصل جهاز التخزين إلى منفذٍ آخر قد يؤدي إلى تغيير هذه القيمة.<br>
		يُفضَّل عادةً استخدام <code>by-label</code> أو <code>by-uuid</code> إذ أنَّ تمثيلها للأقراص ثابتٌ.
	</li>
</ul>
<h3 id="وصل-أجهزة-التخزين-الكتلية">
	وصل أجهزة التخزين الكتلية
</h3>

<p>
	تُستعمَل ملفات الأجهزة الموجودة في <code>‎/dev</code> للتواصل مع التعريف القادر على التعامل مع الجهاز المُعيّن في النواة؛ لكن يجب إنشاء طبقة تُمكّننا من معاملة الجهاز كوسيط تخزين يحتوي على مساحةٍ تخزينيةٍ قابلةٍ للاستعمال.<br>
	في لينكس وغيره من الأنظمة الشبيهة بيونكس (Unix-like)، يُمثَّل نظام التشغيل كشجرة ملفات موحّدة بغض النظر عن عدد الأجهزة الفيزيائية التي تُستعمَل فيه؛ ولكي يُستعمَل نظامُ ملفاتٍ أو قرصٌ في النظام، فيجب ربطه بمكانٍ ما في تلك الشجرة. عملية «الوصل» (mounting) تعني ربط قسم مُهيئ أو قرص إلى مجلدٍ موجودٍ ضمن نظام ملفات لينُكس؛ ومن ثم سنتمكّن من الوصول إلى محتويات القرص أو القسم من ذاك المجلد.<br>
	توصل الأقراص أو الأقسام دومًا في مجلدات فارغة مخصصة لهذا الغرض (الوصل في مجلد غير فارغ يعني أنَّنا لن نتمكن من الوصول إلى محتويات المجلد حتى نفصل [unmount] القرص أو القسم). هنالك الكثير من خيارات الوصل التي يمكن ضبطها لتعديل سلوك الأجهزة الموصولة، على سبيل المثال، يمكن أن يوصل القرص بوضع «القراءة فقط» لضمان عدم تغيير محتوياته.<br>
	ينصح معيار هيكلة نظام الملفات باستخدام <code>‎/mnt</code> أو مجلدٍ فرعيٍ داخله لوصل أنظمة الملفات مؤقتًا. إذا كان وصلك للأقراص مؤقتًا فهذا أفضل مكانٍ لوصلها؛ لكن المعيار لم يُقدِّم أيّة اقتراحات لمكان وصل وسائط التخزين الدائمة، لذا يمكنك وصلها أينما تشاء؛ لكن في أغلبية الحالات توصل وسائط التخزين الدائمة في مجلد <code>‎/mnt</code> أو في مجلدٍ فرعيٍ داخله.
</p>

<h3 id="جعل-الوصل-دائما-باستخدام-etcfstab">
	جعل الوصل دائمًا باستخدام ‎/etc/fstab
</h3>

<p>
	تنظر أنظمة لينكس إلى ملفٍ يدعى <code>‎/etc/fstab</code> (أي filesystem table) الذي يُحدِّد ما هي أنظمة الملفات التي يجب وصلها أثناء الإقلاع. توصل أنظمة الملفات غير الموجودة في ذاك الملف تلقائيًا (باستثناء تلك المُعرَّفة بملفات systemd‏ <code>‎.mount</code>، التي ليست شائعةً حاليًا).<br>
	ملف <code>‎/etc/fstab</code> بسيطٌ جدًا، فكلُ سطرٍ فيه يُمثِّل نظام ملفاتٍ مختلفٍ الذي يجب أن يوصل؛ يُحدِّد هذا السطر ما هو الجهاز الكتلي، وما هي نقطة الوصل (mount point) التي سيُربَط إليها، وما هي صيغة القسم، وما هي خيارات الوصل، بالإضافة إلى معلوماتٍ أخرى.
</p>

<h2 id="إدارة-متقدمة-لأجهزة-التخزين">
	إدارة متقدمة لأجهزة التخزين
</h2>

<p>
	صحيحٌ أنَّ أغلبية الاستخدامات البسيطة لا تحتاج إلى بُنى إدارية إضافية، إلا أنَّنا سنحصل على أداءٍ عالٍ ومرونة وقدرة على تعويض تلف الأقراص عند استخدامنا لطرائق الإدارة المتقدمة.
</p>

<h3 id="ما-هي-مصفوفات-raid">
	ما هي مصفوفات RAID؟
</h3>

<p>
	مصفوفات RAID ترمز إلى «redundant array of independent disks»، وهي تقنية إدارة تخزين تسمح لك بتجميع الأجهزة مع بعضها لإدارتها كجهاز تخزين وحيد له ميزاتٌ إضافيةٌ.<br>
	خصائص مصفوفة RAID تعتمد على مستوى RAID المستعمل، والذي يُعرِّف ما هو عدد الأقراص في المصفوفة وكيف تتعلق ببعضها. للمستوى المختار تأثيرٌ على الأداء والقدرة على تعويض تلف الأقراص، بعض المستويات الشائعة هي:
</p>

<ul>
<li>
		RAID 0: يعتمد هذا المستوى على «توزيع البيانات» (drive striping) والذي يعني أنَّه عندما تُكتَب البيانات إلى المصفوفة، فستُقسَّم وتوزَّع على الأقراص الموجودة في المصفوفة، وهذا يعني زيادةً في الأداء لأنَّ بالإمكان الكتابة على أو القراءة من أكثر من قرص في آنٍ واحد. الجانب السلبي لهذا المستوى هو عندما يحدث عطبٌ في أحد الأقراص فسنفقد جميع المعلومات في كامل المصفوفة، لعدم وجود قرص يحتوي على معلوماتٍ كافيةٍ لإعادة بناء المصفوفة.
	</li>
	<li>
		RAID 1: مستوى RAID 1 يعتمد على إنشاء نسخة مماثلة للبيانات (drive mirroring). فأي شيء يُكتَب إلى مصفوفة RAID 1 سيُكتَب على عدِّة أقراص؛ الميزة الأساسية لهذا المستوى هو القدرة على تعويض الأقراص، مما يعني أنَّ البيانات ستبقى موجودةً في المصفوفة حتى لو حدث عطبٌ في أحد الأقراص؛ وذلك لأنَّ عدِّة أقراص تحتوي على نفس البيانات، لكن في المقابل سيؤدي ذلك تقليل المساحة التخزينية للمصفوفة إلى النصف.
	</li>
	<li>
		RAID 5: مستوى RAID 5 يوزِّع البيانات على عدِّة أقراص بشكلٍ شبيهٍ بمستوى RAID 0؛ لكن هذا المستوى يتضمن تكرار توزيع جزء من البيانات على قرصٍ آخر، وهذا يعني أنَّه لو حدثت مشكلة في أحد الأقراص، فستتمكن بقية الأقراص من إعادة بناء المصفوفة باستخدام البيانات المُكرَّرة التي يمكن تجميعها معًا. تلك البيانات المكررة كافية لإعادة بناء قرصٍ وحيد، وهذا يعني أنَّ المصفوفة ستتمكن من إعادة بناء نفسها إن حدث عطبٌ في قرصٍ وحيدٍ فقط. يؤدي تكرار توزيع البيانات إلى تقليل المساحة التخزينية لكامل المصفوفة إلى ما يعادل المساحة التخزينية لقرصٍ وحيد.
	</li>
	<li>
		RAID 6: يملك المستوى RAID 6 نفس خصائص RAID 5، إلا أنَّه يُكرِّر جزءًا من البيانات على قرصين، وهذا يعني أنَّ مصفوفات RAID 6 ستتمكن من إعادة بناء نفسها إن فقدت قرصين؛ وستتأثر المساحة التخزينية لكامل المصفوفة بتكرار البيانات، وهذا يعني أنَّ المساحة التخزينية القابلة للاستخدام لكامل المصفوفة مساويةٌ للمساحة التخزينية لقرصين.
	</li>
	<li>
		RAID 10: هذا المستوى هو دمجٌ بين المستويين 1 و 0، فبدايةً ستُنشَأ مجموعتين متماثلتين (mirrored) من المصفوفات؛ ثم ستُوزَّع البيانات عليها، وهذا يُنشِئ مصفوفةً لها نفس القدرة التعويضية لكن أداءها عالٍ. لكن هذا المستوى يتطلب عددًا كبيرًا نسبيًا من الأقراص، والمساحة التخزينية القابلة للاستخدام هي نصف مساحة جميع الأقراص.
	</li>
</ul>
<h3 id="ما-هو-lvm">
	ما هو LVM؟
</h3>

<p>
	LVM، أو مدير الحجوم المنطقية (Logical Volume Manager) هو نظامٌ يُشكِّل «طبقةً» تعلو البنية الفيزيائية لوسائط التخزين وخصائصها لتوفير مرونة عالية وقدرات كبيرة. يسمح لك LVM بإنشاء مجموعة من الأجهزة الفيزيائية وإدارتها كما لو أنَّها قرصٌ وحيد، ويمكنك تقسيم المساحة عند الحاجة إلى «حجوم منطقية» (logical volumes) والتي تعمل عمل الأقسام.<br>
	يعمل LVM بناءً على الأقسام العادية، ويحّل الكثير من المحدوديات الموجودة في الأقسام التقليدية، فعلى سبيل المثال، يمكنك بكل سهولة عند استخدام حجوم LVM أن توسِّع الأقسام وتُنشِئ أقسامًا تمتد على أكثر من قرص، وتأخذ نسخ snapshot من الأقسام، وتنقل الحجوم إلى أقراص فيزيائية مختلفة. يجدر بالذكر أنَّ بالإمكان استخدام LVM مع مصفوفات RAID ذات الأداء والوفرة العالية لتوفير نظام إدارة مرن.
</p>

<h2 id="ما-هي-الخطوة-القادمة">
	ما هي الخطوة القادمة؟
</h2>

<p>
	إذا كان لديك جهاز تخزين جديد تريد استخدامه مع نظام لينكس، فألقِ نظرةً على <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%82%D8%B3%D9%8A%D9%85-%D9%88%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r300/" rel="">هذه المقالة</a> التي ستُرشِدُكَ إلى طريقة تقسيم وتهيئة ووصل نظام الملفات الجديد الذي ستُنشِئه. يجب أن تكفيك المقالة السابقة لأغلبية حالات الاستخدام حيث سيكون همّك الرئيسي هو زيادة القدرات التخزينية. لتعلم المزيد عن مهام إدارة أجهزة التخزين الأساسية، فانظر إلى <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%AC%D8%B1%D8%A7%D8%A1-%D9%85%D9%87%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r302/" rel="">هذه المقالة</a><br>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/an-introduction-to-storage-terminology-and-concepts-in-linux" rel="external nofollow">An Introduction to Storage Terminology and Concepts in Linux</a> لصاحبه Justin Ellingwood
</p>
]]></description><guid isPermaLink="false">301</guid><pubDate>Tue, 13 Dec 2016 10:37:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x62C;&#x631;&#x627;&#x621; &#x645;&#x647;&#x627;&#x645; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x623;&#x62C;&#x647;&#x632;&#x629; &#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x627;&#x644;&#x628;&#x633;&#x64A;&#x637;&#x629; &#x641;&#x64A; &#x644;&#x64A;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%AC%D8%B1%D8%A7%D8%A1-%D9%85%D9%87%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r302/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/how-to-perform-basic-administration-tasks-for-storage-devices-in-linux.png.ce6a09a1ce6ec0ecbfa26cf20c62dd6e.png" /></p>

<h2 id="كيفية-إجراء-مهام-إدارة-أجهزة-التخزين-البسيطة-في-لينكس">
	تمهيد
</h2>

<p>
	هنالك الكثير من الأدوات المتوفرة لإدارة التخزين في لينكس، لكن هنالك عددٌ قليلٌ منها نستعمله يوميًا لإدارة وصيانة أجهزة التخزين. سأريك في هذا الدرس بعضًا من أشهر الأدوات التي تستعمل لإدارة نقاط الوصل وأجهزة التخزين وأنظمة الملفات.<br>
	لن نشرح في هذا الدرس كيفية تهيئة أجهزة التخزين لأوّل استعمال لها في لينكس، إذ شرحنا ذلك في درسٍ بعنوان «<a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%82%D8%B3%D9%8A%D9%85-%D9%88%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r300/" rel="">كيفية تقسيم وتهيئة أجهزة التخزين في لينكس</a>» الذي يبيّن لك كيفية إعداد جهاز تخزين جديد إن لم يكن مضبوطًا من قبل.<br>
	للمزيد من المعلومات حول الاصطلاحات والمفاهيم المستخدمة في هذا الدرس، فراجع درس «<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D9%8F%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r301/" rel="">تقديم إلى اصطلاحات ومفاهيم التخزين في لينكس</a>».
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="21820" data-unique="4j5b7qvjr" src="https://academy.hsoub.com/uploads/monthly_2017_02/how-to-perform-basic-administration-tasks-for-storage-devices-in-linux.png.7af8c257528cdff6b41f0aae025ee17b.png" style="" alt="how-to-perform-basic-administration-tasks-for-storage-devices-in-linux.png"></p>

<h2 id="معرفة-القدرة-التخزينية-والمساحة-المستخدمة-عبر-df">
	معرفة القدرة التخزينية والمساحة المستخدمة عبر df
</h2>

<p>
	غالبًا ما تكون أهم معلومة تريد معرفتها عن وسائط التخزين في جهازك هي القدرة التخزينية والمساحة المستخدمة في أجهزة التخزين الموصولة إلى النظام.<br>
	لمعرفة ما المساحة التخزينية المتوافرة إجمالًا وكم نسبة استخدامها، فسنستعين بالأمر <code>df</code>، الذي يعرض ناتجه مقدرًا بالكيلوبايت، لكنك لن تستفيد عادةً من ذلك لذا أضف الخيار <code>‎-h</code> إلى الناتج لعرضه بصيغةٍ سهلة القراءة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs erlang-repl"><span class="hljs-function_or_atom"><span class="pln">df</span></span><span class="pln"> </span><span class="pun">-</span><span class="hljs-function_or_atom"><span class="pln">h</span></span><span class="pln">

</span><span class="hljs-variable"><span class="typ">Filesystem</span></span><span class="pln">      </span><span class="hljs-variable"><span class="typ">Size</span></span><span class="pln">  </span><span class="hljs-variable"><span class="typ">Used</span></span><span class="pln"> </span><span class="hljs-variable"><span class="typ">Avail</span></span><span class="pln"> </span><span class="hljs-variable"><span class="typ">Use</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="typ">Mounted</span><span class="pln"> on</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">udev</span></span><span class="pln">            </span><span class="hljs-number"><span class="lit">238</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">238</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">0</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="pun">/</span><span class="pln">dev</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">tmpfs</span></span><span class="pln">            </span><span class="hljs-number"><span class="lit">49</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">624</span></span><span class="hljs-variable"><span class="lit">K</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">49</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">2</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="pun">/</span><span class="pln">run</span></span><span class="pln">
</span><span class="pun">/</span><span class="hljs-function_or_atom"><span class="pln">dev</span></span><span class="pun">/</span><span class="hljs-function_or_atom"><span class="pln">vda1</span></span><span class="pln">        </span><span class="hljs-number"><span class="lit">20</span></span><span class="hljs-variable"><span class="lit">G</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">1.1</span></span><span class="hljs-variable"><span class="lit">G</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">18</span></span><span class="hljs-variable"><span class="lit">G</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">6</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="pun">/</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">tmpfs</span></span><span class="pln">           </span><span class="hljs-number"><span class="lit">245</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">245</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">0</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="str">/dev/</span><span class="pln">shm</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">tmpfs</span></span><span class="pln">           </span><span class="hljs-number"><span class="lit">5.0</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">5.0</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">0</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="str">/run/</span><span class="kwd">lock</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">tmpfs</span></span><span class="pln">           </span><span class="hljs-number"><span class="lit">245</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">245</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">0</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="str">/sys/</span><span class="pln">fs</span><span class="pun">/</span><span class="pln">cgroup</span></span><span class="pln">
</span><span class="hljs-function_or_atom"><span class="pln">tmpfs</span></span><span class="pln">            </span><span class="hljs-number"><span class="lit">49</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">49</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">0</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="str">/run/</span><span class="pln">user</span><span class="pun">/</span><span class="lit">1000</span></span><span class="pln">
</span><span class="pun">/</span><span class="hljs-function_or_atom"><span class="pln">dev</span></span><span class="pun">/</span><span class="hljs-function_or_atom"><span class="pln">sda1</span></span><span class="pln">        </span><span class="hljs-number"><span class="lit">99</span></span><span class="hljs-variable"><span class="lit">G</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">60</span></span><span class="hljs-variable"><span class="lit">M</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">94</span></span><span class="hljs-variable"><span class="lit">G</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-comment"><span class="pun">%</span><span class="pln"> </span><span class="str">/mnt/</span><span class="pln">data</span></span></code></pre>

<p>
	وكما تلاحظ، القسم <code>‎/dev/vda1</code> الموصول في <code>/</code> ممتلئٌ بنسبة 6% وفيه 18 غيغابايت من المساحة التخزينية الفارغة، بينما القسم <code>‎/dev/sda1</code> موصولٌ في <code>‎/mnt/data</code> وهو فارغٌ وفيه 94 غيغابايت من المساحة التخزينية. الأسطر الأخرى تستخدم أنظمة الملفات <code>tmpfs</code> و <code>devtmpfs</code> والتي هي الذاكرة المؤقتة (volatile memory) ممثلةً كما لو أنَّها وسيطُ تخزينٍ دائمٍ. يمكننا استثناء تلك القيم من الناتج بكتابة الأمر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">df </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">h</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">x</span></span><span class="pln"> tmpfs </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">x</span></span><span class="pln"> devtmpfs

</span><span class="typ">Filesystem</span><span class="pln">      </span><span class="typ">Size</span><span class="pln">  </span><span class="typ">Used</span><span class="pln"> </span><span class="typ">Avail</span><span class="pln"> </span><span class="typ">Use</span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="typ">Mounted</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">on</span></span><span class="pln">
</span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">vda1        </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">1.1</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">18</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">6</span></span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">/</span></span><span class="pln">
</span><span class="str">/dev/</span><span class="pln">sda1        </span><span class="hljs-number"><span class="lit">99</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">60</span></span><span class="lit">M</span><span class="pln">   </span><span class="hljs-number"><span class="lit">94</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="str">/mnt/</span><span class="hljs-built_in"><span class="pln">data</span></span></code></pre>

<p>
	الناتج الحالي يُركِّز على عرض استخدام الأقراص بإزالة بعض الأجهزة الخاصة التي لن ننظر إليها عادةً.
</p>

<h2 id="معرفة-معلومات-عن-الأجهزة-الكتلية-باستخدام-lsblk">
	معرفة معلومات عن الأجهزة الكتلية باستخدام lsblk
</h2>

<p>
	الجهاز الكتلي هو قطعةٌ من العتاد التي يمكن استعمالها لتخزين البيانات، مثل أقراص التخزين الصلبة الاعتيادية (HDD) أو أقراص التخزين ذات الحالة الثابتة (solid state drive أي SSD) أو وحدات الذاكرة الفلاشية (flash memory stick) …إلخ. والأجهزة الكتلية هي أقراصٌ فيزيائيةٌ التي تُكتَب عليها أنظمة الملفات، وتُحدِّد أنظمة الملفات بدورها كيفية تخزين الملفات والبيانات على القرص.<br>
	يمكن استعمال الأداة <code>lsblk</code> لعرض معلومات عن الأجهزة الكتلية الموجودة في النظام. تَتبَع الميزات المتاحة لهذه الأداة للنسخة المُثبَّتة، لكن يمكن عمومًا استخدام الأداة <code>lsblk</code> لعرض معلومات عن القرص نفسه، بالإضافة إلى عرض معلومات عن طريقة التقسيم وأنظمة الملفات التابعة لتلك الأقسام.<br>
	إذا نفّذنا الأمر <code>lsblk</code> دون وسائط فسيُظهِر أسماء الأجهزة، والأرقام الرئيسية (major) والثانوية (minor) والتي تستخدم من نواة لينكس لتتبع الأقراص والأجهزة، وفيما إذا كان القرص قابلًا للإزالة، ومساحته التخزينية، وفيما إذا كان موصولًا بنمط «القراءة فقط»، ونوعه (أي قرص أم قسم)، ونقطة الوصل. تتطلب بعض الأنظمة استخدام امتيازات الجذر (أي استخدام الأمر <code>sudo</code>) لعرض الناتج عرضًا صحيحًا، وهذا ما سنفعل في المثال الآتي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo lsblk

NAME   MAJ</span><span class="pun">:</span><span class="hljs-keyword"><span class="pln">MIN</span></span><span class="pln"> RM  SIZE RO </span><span class="hljs-keyword"><span class="pln">TYPE</span></span><span class="pln"> MOUNTPOINT
sda      </span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">  </span><span class="hljs-number"><span class="lit">100</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
vda    </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
</span><span class="pun">└─</span><span class="pln">vda1 </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> part </span><span class="hljs-subst"><span class="pun">/</span></span></code></pre>

<p>
	أهم الأجزاء المعروضة في الناتج السابق هي الاسم الذي يُشير إلى اسم الجهاز في مجلد <code>‎/dev</code>، ومساحته التخزينية، ونقطة الوصل. يمكنك أن ترى في الناتج السابق أنَّنا نملك قرصًا (<code>‎/dev/vda</code>) فيه قسمٌ وحيد (<code>‎/dev/vda1</code>) الموصول في <code>/</code> وقرصًا آخر (<code>‎/dev/sda</code>) الذي لم يُقسَّم بعد.<br>
	للحصول على معلوماتٍ متعلقة بإدارة القرص والقسم، فمرِّر الخيار <code>‎--fs</code> الذي يعمل في بعض الإصدارات:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> lsblk </span><span class="pun">--</span><span class="pln">fs

NAME   FSTYPE LABEL  UUID                                 MOUNTPOINT
sda                                                       
vda                                                       
</span><span class="pun">└─</span><span class="pln">vda1 ext4   DOROOT c154916c</span><span class="pun">-</span><span class="hljs-number"><span class="lit">06</span></span><span class="lit">ea</span><span class="pun">-</span><span class="hljs-number"><span class="lit">4268</span></span><span class="pun">-</span><span class="hljs-number"><span class="lit">819</span></span><span class="lit">d</span><span class="pun">-</span><span class="pln">c0e36750c1</span><span class="hljs-built_in"><span class="pln">cd</span></span><span class="pln"> </span><span class="pun">/</span></code></pre>

<p>
	إذا لم يكن الخيار <code>‎--fs</code> متوافرًا في نسختك، فيمكنك أن تطلب إظهار نفس الناتج السابق باستخدام الخيار <code>‎-o NAME,FSTYPE,LABEL,UUID,MOUNTPOINT‎</code>.<br>
	للحصول على معلومات حول بنية القرص، فنفِّذ الأمر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo lsblk </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">t</span></span><span class="pln">

NAME   ALIGNMENT </span><span class="hljs-keyword"><span class="pln">MIN</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">IO</span></span><span class="pln"> OPT</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">IO</span></span><span class="pln"> PHY</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">SEC</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">LOG</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">SEC</span></span><span class="pln"> ROTA SCHED    RQ</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">SIZE</span></span><span class="pln">  RA WSAME
sda            </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">      </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> deadline     </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">2</span></span><span class="lit">G</span><span class="pln">
vda            </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">      </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">              </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="lit">B</span><span class="pln">
</span><span class="pun">└─</span><span class="pln">vda1         </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">      </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">     </span><span class="hljs-number"><span class="lit">512</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">              </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">128</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="lit">B</span></code></pre>

<p>
	هنالك المزيد من الاختصارات المتوافرة لعرض مختلف المعلومات عن أقراصك وأقسامك. يمكنك عرض جميع المعلومات باستخدام الخيار <code>‎-0</code> أو يمكنك تحديد ما هي الحقول التي تريدها بتحديد اسمها باستخدام الخيار <code>‎-o</code>. خيار المساعدة <code>‎-h</code> سيعرض جميع الحقول المتاحة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs applescript"><span class="pln">lsblk </span><span class="pun">-</span><span class="pln">h

</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="typ">Available</span><span class="pln"> columns </span><span class="pun">(</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> </span><span class="hljs-comment"><span class="pun">--</span><span class="pln">output</span><span class="pun">):</span></span><span class="pln">
        NAME  device </span><span class="hljs-property"><span class="pln">name</span></span><span class="pln">
       KNAME  </span><span class="kwd">internal</span><span class="pln"> kernel device </span><span class="hljs-property"><span class="pln">name</span></span><span class="pln">

       </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

  SUBSYSTEMS  de</span><span class="pun">-</span><span class="pln">duplicated chain </span><span class="hljs-keyword"><span class="pln">of</span></span><span class="pln"> subsystems
         REV  device revision
      VENDOR  device vendor

</span><span class="typ">For</span><span class="pln"> more details see lsblk</span><span class="pun">(</span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">).</span></code></pre>

<h2 id="فصل-ووصل-أنظمة-الملفات">
	فصل ووصل أنظمة الملفات
</h2>

<p>
	عليك قبل استخدامٍ قرصٍ جديدٍ أن تُقسِّمه، وأن تُهيئه بنظام ملفاتٍ معيّن، ثم تصله. عملية التقسيم والتهيئة تُجرى عادةً لمرة واحدة، لذا لن نناقشها هنا، وكما ذكرتُ في بداية هذا الدرس، تستطيع العثور على معلوماتٍ تفصيلية حول تقسيم قرص وتهيئة قسمٍ فيه <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%82%D8%B3%D9%8A%D9%85-%D9%88%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r300/" rel="">في هذه المقالة</a>.<br>
	أما الوصل (mounting) فهو أمرٌ تفعله كل حين، فوصل نظام ملفاتٍ يعني أنَّه أصبح متاحًا للاستخدام داخل النظام في نقطة الوصل المُحدَّدة. ونقطة الوصل هي مجلدٌ الذي يمكننا الوصول عبره إلى نظام الملفات.<br>
	يوجد أمرَين يُكمِّلان بعضها بعضًا ويستخدمان لإدارة عملية الوصل هما <code>mount</code> و <code>umount</code>. يُستعمَل الأمر <code>mount</code> لوصل نظام ملفات إلى شجرة الملفات الحالية، ففي نظام لينكس هنالك شجرة ملفات وحيدة لكامل النظام بغض النظر عن عدد الأجهزة الفيزيائية التي تتألف منها. أما الأمر <code>umount</code> (انتبه أنَّ اسم الأمر هو <code>umount</code> وليس <code>unmount</code>) فيُستعمَل لفصل نظام ملفات. إضافةً إلى الأمرين السابقين، يوجد أمرٌ باسم <code>findmnt</code> الذي يفيد بجمع معلومات عن حالة أنظمة الملفات الموصولة.
</p>

<h3 id="استخدام-الأمر-mount">
	استخدام الأمر mount
</h3>

<p>
	أبسط طريقة لاستخدام <code>mount</code> هي تمرير مسار القسم ثم نقطة الوصل التي تريد وصله إليها:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> mount </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 </span><span class="pun">/</span><span class="pln">mnt</span></code></pre>

<p>
	نقطة الوصل –التي هي آخر وسيط والذي يُحدِّد أين يجب وصل نظام الملفات الجديد– يجب أن تُشير دائمًا إلى مجلدٍ فارغ.<br>
	يمكنك تحديد بعض الخيارات عند الوصل، وصحيحٌ أنَّ الأمر <code>mount</code> سيحاول معرفة نوع نظام الملفات، لكن من الأفضل تمرير نوع نظام الملفات عبر الخيار <code>‎-t</code>. فلنظام ملفات Ext4 نكتب:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> mount </span><span class="pun">-</span><span class="pln">t ext4 </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 </span><span class="pun">/</span><span class="pln">mnt</span></code></pre>

<p>
	هنالك الكثير من الخيارات الأخرى التي تُغيّر طريقة وصل نظام الملفات؛ حيث تتواجد خيارات الوصل العامة في قسم «FILESYSTEM INDEPENDENT MOUNT OPTIONS» في صفحة الدليل <code>man mount</code>، ويوجد أيضًا أقسام لمختلف أنظمة الملفات تحت عنوان «FILESYSTEM SPECIFIC MOUNT OPTIONS» في نفس صفحة الدليل السابقة لشرح الخيارات الخاصة بأنظمة ملفات معيّنة.<br>
	يمكنك تمرير الخيارات الأخرى باستخدام <code>‎-o</code>، فمثلًا يمكنك وصل القسم باستخدام الخيارات الافتراضية (والتي هي <code>rw,suid,dev,exec,auto,nouser,async</code>) بكتابة <code>‎-o defaults</code>، أما إذا أردتَ مثلًا أن تتجاوز إذن السماح بالقراءة والكتابة وتريد وصل القسم للقراءة فقط، فيكنك إضافة الخيار <code>ro</code> والذي سيتجاوز الخيار <code>rw</code> من <code>defaults</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">sudo mount </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">t</span></span><span class="pln"> ext4 </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">o</span></span><span class="pln"> defaults</span><span class="pun">,</span><span class="pln">ro </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 </span><span class="pun">/</span><span class="pln">mnt</span></code></pre>

<p>
	لوصل جميع أنظمة الملفات الموجودة في ملف <code>‎/etc/fstab</code> فمرِّر الخيار <code>‎-a</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> mount </span><span class="hljs-operator"><span class="pun">-</span><span class="pln">a</span></span></code></pre>

<h3 id="عرض-خيارات-وصل-أنظمة-الملفات">
	عرض خيارات وصل أنظمة الملفات
</h3>

<p>
	يمكن عرض خيارات الوصل المستعملة مع قسمٍ معيّن بتمرير مسار نقطة الوصل إلى الأمر <code>findmnt</code>، فمثلًا لو مررنا نقطة الوصل التي استعملناها في المثال السابق لوصل نظام الملفات للقراءة فقط إلى الأمر <code>findmnt</code> فسيبدو الناتج شبيهًا بما يلي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">findmnt</span></span><span class="pln"> </span><span class="pun">/</span><span class="pln">mnt

</span><span class="hljs-type"><span class="pln">TARGET</span></span><span class="pln"> </span><span class="hljs-type"><span class="pln">SOURCE</span></span><span class="pln">    </span><span class="hljs-type"><span class="pln">FSTYPE</span></span><span class="pln"> </span><span class="hljs-type"><span class="pln">OPTIONS</span></span><span class="pln">
</span><span class="pun">/</span><span class="pln">mnt   </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 ext4   ro</span><span class="pun">,</span><span class="pln">relatime</span><span class="pun">,</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span><span class="pun">=</span><span class="pln">ordered</span></span></code></pre>

<p>
	يمكن أن تستفيد من هذا خير استفادة إن كنت تجرِّب عدِّة خيارات ووجدت ضالتك في إحداها، فتستطيع حينها أن تستعمل <code>findmnt</code> لمعرفة ما هي خيارات الوصل لإضافتها إلى ملف <code>‎/etc/fstab</code> أو إذا أردتَ وصل القسم يدويًا في المستقبل.
</p>

<h3 id="فصل-نظام-الملفات">
	فصل نظام الملفات
</h3>

<p>
	يستعمل الأمر <code>umount</code> لفصل نظام ملفات معيّن، أكرِّر أنَّ الأمر هو <code>umount</code> وليس <code>unmount</code>.<br>
	الشكل العام للأمر بسيطٌ جدًا وهو تمرير نقطة الوصل أو الجهاز الموصول إلى الأمر <code>umount</code>. تأكّد أنَّك لا تستخدم أيّة ملفات في نقطة الوصل ولا توجد أيّة برامج (بما في ذلك الصَدَفَة [shell] التي تستعملها) تعمل داخل نقطة الوصل:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">cd</span></span><span class="pln"> </span><span class="pun">~</span><span class="pln">
</span><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> umount </span><span class="pun">/</span><span class="pln">mnt</span></code></pre>

<p>
	لن تحتاج غالبًا إلى أيّة خيارات خاصة عند فصل أنظمة الملفات.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	صحيحٌ أنَّ الأدوات التي شرحناها في مقالتنا هذه ليس كثيرةً، لكنها تكفي احتياجاتك اليومية بخصوص إدارة الأقسام وأجهزة التخزين.<br>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-perform-basic-administration-tasks-for-storage-devices-in-linux" rel="external nofollow">How To Perform Basic Administration Tasks for Storage Devices in Linux</a> لصاحبه Justin Ellingwood
</p>
]]></description><guid isPermaLink="false">302</guid><pubDate>Tue, 06 Dec 2016 23:00:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x642;&#x633;&#x64A;&#x645; &#x648;&#x62A;&#x647;&#x64A;&#x626;&#x629; &#x623;&#x62C;&#x647;&#x632;&#x629; &#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x641;&#x64A; &#x644;&#x64A;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%82%D8%B3%D9%8A%D9%85-%D9%88%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A3%D8%AC%D9%87%D8%B2%D8%A9-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r300/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_02/how-to-partition-and-format-storage-devices-in-linux.png.f09db611e345f4b9a4bb423c420c9704.png" /></p>

<h2 id="كيفية-تقسيم-وتهيئة-أجهزة-التخزين-في-لينكس">
	تمهيد
</h2>

<p>
	يمكن أن يكون تحضير قرصٍ جديدٍ للاستخدام في نظام لينكس سهلًا وسريعًا، حيث هنالك الكثير من الأدوات، وصيغ أنظمة الملفات، ومخططات التقسيم التي يمكن أن تُعقِّد العملية إذا كانت لديك احتياجيات خاصة، لكن إن أردتَ أن تُشغِّل جهاز التخزين بسرعة، فالأمر سهلٌ جدًا.<br>
	سنشرح في هذا الدرس العمليات الآتية:
</p>

<ul>
<li>
		التعرف على قرصٍ جديدٍ في النظام.
	</li>
	<li>
		إنشاء قسمٍ وحيدٍ الذي يمتد على كامل القرص (تتوقع أغلبية أنظمة التشغيل وجود جدول أقسام، حتى لو كان هنالك نظام ملفاتٍ وحيدٍ في القرص).
	</li>
	<li>
		تهيئة القسم بنظام ملفات Ext4 (نظام الملفات الافتراضي في أغلبية توزيعات لينكس).
	</li>
	<li>
		وصل وضبط الوصل التلقائي لنظام الملفات عند الإقلاع.
	</li>
</ul>
<h1 style="text-align: center;">
	<img alt="how-to-partition-and-format-storage-devices-in-linux.png" class="ipsImage ipsImage_thumbnailed" data-fileid="21818" data-unique="rixk9a9t0" src="https://academy.hsoub.com/uploads/monthly_2017_02/how-to-partition-and-format-storage-devices-in-linux.png.84014f3f8e2f0ea771960deccd687b50.png" style="">
</h1>

<h2 id="تثبيت-الأدوات">
	تثبيت الأدوات
</h2>

<p>
	علينا استخدام الأداة <code>parted</code> لتقسيم القرص، وقد تكون مثبتةً على الخادوم في أغلبية الحالات.<br>
	إذا كنتَ على خادوم أوبنتو أو دبيان ولم تكن الأداة <code>parted</code> مثبتةً بعد، فيمكنك تثبيتها بكتابة ما يلي في سطر الأوامر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> update
</span><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install parted</span></code></pre>

<p>
	أما إذا كنتَ على خادوم CentOS أو فيدورا، فيمكنك تثبيتها بكتابة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> yum install parted</span></code></pre>

<h2 id="التعرف-على-القرص-الجديد-في-النظام">
	التعرف على القرص الجديد في النظام
</h2>

<p>
	قبل أن نضبط القرص، فيجب أن نتمكن من التعرف عليه بشكلٍ صحيحٍ في الخادوم.<br>
	إذا كان القرص جديدًا كليًّا، فأسهل طريقة للتعرف عليه في الخادوم هي معرفة إن كان جدول التقسيمات موجودًا. فإذا طلبنا من <code>parted</code> أن يعرض مخطط الأقسام لجميع أقراصنا، فسيعطينا رسالة خطأ لأيّة أقراص لا تملك مخطط أقسام صحيح. يمكننا أن نستعمل هذه المعلومة لمساعدتنا على التعرف على القرص الجديد:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> parted </span><span class="hljs-operator"><span class="pun">-</span><span class="pln">l</span></span><span class="pln"> </span><span class="pun">|</span><span class="pln"> grep </span><span class="typ">Error</span></code></pre>

<p>
	يجب أن ترى رسالة الخطأ <code>unrecognized disk label</code> للأقراص الجديدة غير المُقسَّمة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs javascript"><span class="hljs-built_in"><span class="typ">Error</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-regexp"><span class="str">/dev/</span></span><span class="pln">sda</span><span class="pun">:</span><span class="pln"> unrecognised disk label</span></code></pre>

<p>
	يمكنك أيضًا استخدام الأمر <code>lsblk</code> والبحث عن القرص الذي له المساحة التخزينية الصحيحة وليس له أيّة أقسام تابعة له:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs "><span class="pln">lsblk</span></code></pre>

<p>
	الناتج:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">NAME   MAJ</span><span class="pun">:</span><span class="hljs-keyword"><span class="pln">MIN</span></span><span class="pln"> RM   SIZE RO </span><span class="hljs-keyword"><span class="pln">TYPE</span></span><span class="pln"> MOUNTPOINT
sda      </span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">100</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
vda    </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
</span><span class="pun">└─</span><span class="pln">vda1 </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> part </span><span class="hljs-subst"><span class="pun">/</span></span></code></pre>

<p>
	تحذير: تذكر أنَّ عليك التحقق من ناتج <code>lsblk</code> في كل مرة قبل إجراء التغييرات. فمُعرِّفات الأقراص <code>‎/dev/sd*‎</code> و <code>‎/dev/hd*‎</code> قد لا تشير إلى نفس القرص بعد إعادة الإقلاع، وهذا يعني أنَّك قد تخاطر بتقسيم أو تهيئة القرص الخاطئ إن لم تتحقق من مُعرِّف القرص قبل ذلك.<br>
	حاول استخدام مُعرِّفات الأقراص الثابتة مثل <code>‎/dev/disk/by-uuid</code> أو <code>‎/dev/disk/by-label</code> أو <code>‎/dev/disk/by-id</code>. راجع مقالة «<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D9%8F%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r301/" rel="">مدخل إلى مُصطلحات ومفاهيم التخزين في لينكس</a>» لمزيد من التفاصيل.<br>
	بعد أن تعلم ما هو الاسم الذي أسندته النواة إلى قرصك، فيمكنك البدء بتقسيمه.
</p>

<h2 id="تقسيم-القرص-الجديد">
	تقسيم القرص الجديد
</h2>

<p>
	كما ذكرنا في التمهيد، سننشِئ قسمًا وحيدًا يمتد على كامل القرص.
</p>

<h3 id="اختيار-أحد-معايير-التقسيم">
	اختيار أحد معايير التقسيم
</h3>

<p>
	علينا أولًا تحديد ما هو معيار التقسيم الذي نود استخدامه، إذ أنَّ GPT هو معيار تقسيم حديث، بينما MBR له دعمٌ واسعٌ في أنظمة التشغيل. إن لم تكن عندك متطلباتٌ خاصة، فمن الأفضل أن تختار GPT.<br>
	نفِّذ الأمر الآتي على القرص الذي تريد تقسيمه لاختيار GPT:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> parted </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda mklabel gpt</span></code></pre>

<p>
	أما إذا أردتَ استخدام MBR، فنفِّذ الأمر الآتي بدلًا من الأمر السابق:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> parted </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda mklabel msdos</span></code></pre>

<h3 id="إنشاء-قسم-جديد">
	إنشاء قسم جديد
</h3>

<p>
	بعد اختيار صيغة جدول الأقسام، فحان الآن الوقت لإنشاء قسم يمتد على كامل القرص بكتابة الأمر الآتي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> parted </span><span class="hljs-operator"><span class="pun">-</span><span class="pln">a</span></span><span class="pln"> opt </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda mkpart primary ext4 </span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">%</span><span class="pln"> </span><span class="hljs-number"><span class="lit">100</span></span><span class="pun">%</span></code></pre>

<p>
	إذا نفَّذنا الأمر <code>lsblk</code> الآن، فسنشاهد القسم الجديد مذكورًا في القائمة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">NAME   MAJ</span><span class="pun">:</span><span class="hljs-keyword"><span class="pln">MIN</span></span><span class="pln"> RM   SIZE RO </span><span class="hljs-keyword"><span class="pln">TYPE</span></span><span class="pln"> MOUNTPOINT
sda      </span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">100</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
</span><span class="pun">└─</span><span class="pln">sda1   </span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">   </span><span class="hljs-number"><span class="lit">100</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> part 
vda    </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> disk 
</span><span class="pun">└─</span><span class="pln">vda1 </span><span class="hljs-number"><span class="lit">253</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">    </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> part </span><span class="hljs-subst"><span class="pun">/</span></span></code></pre>

<h2 id="إنشاء-نظام-ملفات-على-القسم-الجديد">
	إنشاء نظام ملفات على القسم الجديد
</h2>

<p>
	أصبح لدينا الآن قسمٌ جديدٌ متاحٌ للاستخدام، لذا علينا الآن تهيئته بنظام ملفات Ext4؛ وذلك بتمرير مسار القسم إلى الأداة <code>mkfs.ext4</code>.<br>
	يمكننا إضافة لافتة (label) للقسم باستخدام الخيار <code>‎-L</code>. سيساعدك اختيار اسمٍ واضحٍ على التعرف على القسم بسهولة وسرعة.<br>
	ملاحظة: من المهم أنَّ تمرِّر اسم القسم وليس كامل القرص. تذكّر أنَّ أسماء الأقراص في لينُكس تشبه <code>sda</code> و <code>sdb</code> و <code>hda</code> …إلخ. أما الأقسام على تلك الأقراص فلها رقمٌ ملحقٌ بآخر اسمها، أي أنَّ عليك استخدام اسمٍ يشبه <code>sda1</code> وليس <code>sda</code>.
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> mkfs</span><span class="pun">.</span><span class="pln">ext4 </span><span class="pun">-</span><span class="pln">L datapartition </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1</span></code></pre>

<p>
	إذا أردتَ أن تُغيّر لافتة القسم بعد إنشائه، فاستعمل حينها الأمر <code>e2label</code> كما يلي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> e2label </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 newlabel</span></code></pre>

<p>
	يمكننا إظهار جميع الطرائق التي يمكنك التعرف فيها على القسم باستخدام <code>lsblk</code>؛ حيث نريد أن نعرض الاسم ,واللُصيقة ومُعرِّف UUID التابعين للقسم.<br>
	بعض إصدارات <code>lsblk</code> تُظهِر جميع تلك المعلومات إذا كتبنا:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> lsblk </span><span class="pun">--</span><span class="pln">fs</span></code></pre>

<p>
	إذا لم تُظهِر النسخة الموجودة عندك كل الحقول اللازمة، فيمكنك طلب إظهارها يدويًا:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> lsblk </span><span class="pun">-</span><span class="pln">o NAME</span><span class="pun">,</span><span class="pln">FSTYPE</span><span class="pun">,</span><span class="pln">LABEL</span><span class="pun">,</span><span class="pln">UUID</span><span class="pun">,</span><span class="pln">MOUNTPOINT</span></code></pre>

<p>
	يجب أن يظهر لك ناتجٌ شبيهٌ بالناتج الآتي، وكلُّ سطرٍ فيه يضمُّ الطرائق المختلفة التي يمكنك استعمالها للإشارة إلى نظام الملفات الجديد:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">NAME   FSTYPE LABEL         UUID                                 MOUNTPOINT
sda                                                              
</span><span class="pun">└─</span><span class="pln">sda1 ext4   datapartition </span><span class="hljs-number"><span class="lit">4</span></span><span class="lit">b313333</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">a7b5</span></span><span class="hljs-subst"><span class="pun">-</span></span><span class="hljs-number"><span class="lit">48</span></span><span class="lit">c1</span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">a957</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">d77d637e4fda</span></span><span class="pln"> 
vda                                                              
</span><span class="pun">└─</span><span class="pln">vda1 ext4   DOROOT        </span><span class="hljs-number"><span class="lit">050e1</span></span><span class="lit">e34</span><span class="hljs-subst"><span class="pun">-</span></span><span class="hljs-number"><span class="lit">39e6</span></span><span class="hljs-subst"><span class="pun">-</span></span><span class="hljs-number"><span class="lit">4072</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">a03e</span></span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">ae0bf90ba13a</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">/</span></span></code></pre>

<h2 id="وصل-نظام-الملفات-الجديد">
	وصل نظام الملفات الجديد
</h2>

<p>
	يمكنك الآن وصل نظام الملفات لكي تستعمله.<br>
	ينصح <a href="http://refspecs.linuxfoundation.org/fhs.shtml" rel="external nofollow">معيار هيكلة نظام الملفات</a> باستخدام <code>‎/mnt</code> أو مجلدٍ فرعيٍ داخله لوصل أنظمة الملفات مؤقتًا. إذا كان وصلك للأقراص مؤقتًا فهذا أفضل مكانٍ لوصلها؛ لكن المعيار لم يُقدِّم أيّة اقتراحات لمكان وصل وسائط التخزين الدائمة، لذا يمكنك وصلها أينما تشاء؛ سنصل القسم في هذا الدرس داخل المجلد <code>‎/mnt/data</code>.<br>
	أنشِئ المجلد باستخدام الأمر:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">sudo</span></span><span class="pln"> mkdir </span><span class="pun">-</span><span class="pln">p </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span></span></code></pre>

<h3 id="وصل-نظام-الملفات-مؤقتا">
	وصل نظام الملفات مؤقتًا
</h3>

<p>
	إذا أردتَ وصل نظام الملفات مؤقتًا، فنفِّذ الأمر الآتي:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">sudo</span></span><span class="pln"> mount </span><span class="pun">-</span><span class="pln">o defaults </span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">sda1 </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span></span></code></pre>

<h3 id="وصل-نظام-الملفات-تلقائيا-عند-الإقلاع">
	وصل نظام الملفات تلقائيًا عند الإقلاع
</h3>

<p>
	إذا أردتَ أن تصل نظام الملفات تلقائيًا في كل مرة يُقلِع فيها الخادوم، فعدِّل ملف <code>‎/etc/fstab</code> بمحرِّرك النصي المفضَّل:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">fstab</span></code></pre>

<p>
	نفَّذنا سابقًا الأمر <code>sudo lsblk --fs</code> لعرض ثلاثة مُعرِّفات لنظام الملفات الذي أنشأناه؛ يمكننا استخدام أي منها في ملف <code>fstab</code>؛ وسنستعمل في مثالنا هذا طريقة «اللُصيقة» (label)، لكنك تستطيع أن ترى كيف تبدو الأسطر التي تستعمل الطرائق الأخرى مذكورةً في التعليقات:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs vala"><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="hljs-preprocessor"><span class="com">## Use one of the identifiers you found to reference the correct partition</span></span><span class="pln">
</span><span class="hljs-preprocessor"><span class="com"># /dev/sda1 /mnt/data ext4 defaults 0 2</span></span><span class="pln">
</span><span class="hljs-preprocessor"><span class="com"># UUID=4b313333-a7b5-48c1-a957-d77d637e4fda /mnt/data ext4 defaults 0 2</span></span><span class="pln">
LABEL</span><span class="pun">=</span><span class="pln">datapartition </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="pln">data ext4 defaults </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span></code></pre>

<p>
	ملاحظة: يمكنك تعلم المزيد عن مختلف الحقول في ملف <code>‎/etc/fstab</code> في صفحة الدليل <code>man fstab</code>، لمعلوماتٍ إضافيةٍ عن خيارات الوصل المتوفرة لنظام ملفات معيّن فراجع صفحة الدليل <code>man [filesystem]</code> (أي مثلًا <code>man ext4</code>). لكن الأسطر الموجودة في المثال السابق تكفيك مبدئيًا.<br>
	يُضاف الخيار <code>discard</code> في بعض الأحيان لأقراص SSD لتفعيل «TRIM» بشكلٍ مستمر، وهنالك جدالٌ قائمٌ عن تأثير ذلك على الأداء؛ وأغلبية التوزيعات تتضمن طريقةً لإجراء TRIM كل فترة كبديلٍ عن تشغيله بشكلٍ مستمر.<br>
	احفظ الملف الآن بعد أن تنتهي من تعديله.<br>
	إذا لم تصل نظام الملفات من قبل، فيمكنك وصله الآن بكتابة:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> mount </span><span class="hljs-operator"><span class="pun">-</span><span class="pln">a</span></span></code></pre>

<h3 id="اختبار-نظام-الملفات-الموصول">
	اختبار نظام الملفات الموصول
</h3>

<p>
	بعد أن وصلنا القسم، فعلينا أن نتأكد من أنَّنا قادرون على الوصول إلى نظام الملفات.<br>
	يمكننا التحقق إن كان القرص متاحًا بالنظر إلى ناتج الأمر <code>df</code>:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs lasso"><span class="pln">df </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">h</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">x</span></span><span class="pln"> tmpfs </span><span class="hljs-attribute"><span class="pun">-</span><span class="pln">x</span></span><span class="pln"> devtmpfs

</span><span class="typ">Filesystem</span><span class="pln">      </span><span class="typ">Size</span><span class="pln">  </span><span class="typ">Used</span><span class="pln"> </span><span class="typ">Avail</span><span class="pln"> </span><span class="typ">Use</span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="typ">Mounted</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">on</span></span><span class="pln">
</span><span class="pun">/</span><span class="pln">dev</span><span class="pun">/</span><span class="pln">vda1        </span><span class="hljs-number"><span class="lit">20</span></span><span class="lit">G</span><span class="pln">  </span><span class="hljs-number"><span class="lit">1.3</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">18</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">7</span></span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pun">/</span></span><span class="pln">
</span><span class="str">/dev/</span><span class="pln">sda1        </span><span class="hljs-number"><span class="lit">99</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">60</span></span><span class="lit">M</span><span class="pln">   </span><span class="hljs-number"><span class="lit">94</span></span><span class="lit">G</span><span class="pln">   </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-subst"><span class="pun">%</span></span><span class="pln"> </span><span class="str">/mnt/</span><span class="hljs-built_in"><span class="pln">data</span></span></code></pre>

<p>
	يجب أن تشاهد المجلد <code>lost+found</code> داخل المجلد <code>‎/mnt/data</code>، والذي يُشير عادةً إلى جذر أنظمة ملفات Ext*‎:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">ls</span></span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span></span><span class="pln">

</span><span class="hljs-title"><span class="pln">total</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">16</span></span><span class="pln">
</span><span class="hljs-title"><span class="pln">drwx</span></span><span class="hljs-comment"><span class="pun">------</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> root root </span><span class="lit">16384</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">11</span><span class="pun">:</span><span class="lit">10</span><span class="pln"> lost</span><span class="pun">+</span><span class="pln">found</span></span></code></pre>

<p>
	يمكننا أيضًا التحقق من أنَّ نظام الملفات موصولٌ مع القدرة على القراءة والكتابة إليه بالكتابة إلى ملفٍ اختباري:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs bash"><span class="hljs-built_in"><span class="pln">echo</span></span><span class="pln"> </span><span class="hljs-string"><span class="str">"success"</span></span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">sudo</span></span><span class="pln"> tee </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="pln">data</span><span class="pun">/</span><span class="pln">test_file</span></code></pre>

<p>
	اقرأ الملف من القرص للتأكّد من القدرة على قراءة الملفات:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">cat</span></span><span class="pln"> </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span><span class="pun">/</span><span class="pln">test_file</span></span><span class="pln">

</span><span class="hljs-title"><span class="pln">success</span></span></code></pre>

<p>
	يمكنك حذف الملف بعد التحقق من أنَّ نظام الملفات الجديد يعمل عملًا سليمًا:
</p>

<pre class="prettyprint prettyprinted">
<code class="hljs haskell"><span class="hljs-title"><span class="pln">sudo</span></span><span class="pln"> rm </span><span class="pun">/</span><span class="pln">mnt</span><span class="pun">/</span><span class="hljs-typedef"><span class="hljs-keyword"><span class="pln">data</span></span><span class="pun">/</span><span class="pln">test_file</span></span></code></pre>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	يجب أن يكون قرصك الآن مُقسَّمًا ومُهيّئًا وموصولًا وجاهزًا للاستخدام؛ وما شرحناه في هذا الدرس يُمثِّل الخطوط الأساسية لكيفية تحويل قرص خام إلى نظام ملفات يمكن للينكس أن يستعمله للتخزين. هنالك طرائق أخرى أكثر تعقيدًا للتقسيم والتهيئة والوصول والتي قد تستفيد منها في بعض الحالة، لكن ما سبق كافٍ كنقطة انطلاق لكيفية إعداد قرص للاستخدام الاعتيادي.<br>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-partition-and-format-storage-devices-in-linux" rel="external nofollow">How To Partition and Format Storage Devices in Linux</a> لصاحبه Justin Ellingwoo
</p>
]]></description><guid isPermaLink="false">300</guid><pubDate>Mon, 28 Nov 2016 09:28:00 +0000</pubDate></item><item><title>15 &#x645;&#x62B;&#x627;&#x644;&#x627; &#x644;&#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x62D;&#x632;&#x645; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; RPM</title><link>https://academy.hsoub.com/devops/linux/15-%D9%85%D8%AB%D8%A7%D9%84%D8%A7-%D9%84%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-rpm-r283/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_12/rpm.png.d655979092cb1442cedf1fbe4edff31a.png" /></p>

<p>
	تستخدم بعض توزيعات لينكس، خصوصا تلك المعتمدة على Fedora مثل CentOS و<a href="https://academy.hsoub.com/certificates/redhat/rhcsa/" rel="">Red Hat Enterprise Linux</a>، حزم RPM لتثبيت البرامج وإدارتها. ملف <code>rpm.</code> هو عبارة عن تجميع لبرامج ومكتبات تحتاجها هذه البرامج في حزمة تُستخدَم أداة باسم <code>rpm</code> لتثبيتها. الأداة <code>rpm</code> هي أداة مفتوحة المصدر تحتفظ ببيانات الحزم المثبّتة على النظام في المجلّد <code>var/lib/rpm/</code>. من المهم الانتباه إلى أن أداة <code>rpm</code> لا تستطيع التعامل مع البرامج التي ثُبِّتت انطلاقا من المصدر Source. يحتوي ملفّ <code>rpm.</code> على معلومات من قبيل ماهية الحزمة، من أين تأتي، الاعتماديات التي تحتاجها للعمل، الإصدار… إلخ.
</p>

<p>
	توجد خمسة أوضاع أساسية لأداة <code>rpm</code>:
</p>

<ul>
<li>
		التثبيت <code>i-</code>: يُستخدَم لتثبيت حزم RPM.
	</li>
	<li>
		الحذف <code>e-</code>: يُستخدَم لحذف حزمة وإلغاء تثبيتها.
	</li>
	<li>
		الترقية <code>U-</code>: يُحدّث حزمة مثبّتة (تثبيت إصدار جديد من الحزمة).
	</li>
	<li>
		التحقق <code>V-</code>: يُستخدَم للتحقّق من حزمة RPM.
	</li>
	<li>
		الاستعلام <code>q-</code>: يُستخدَم للاستعلام عن حزم RPM.
	</li>
</ul>
<p>
	حزم RPM هي حزم قائمة بذاتها؛ تمكن الاستفادة من المواقع التالية للحصول على حزم RPM الخاصّة ببرنامج تريده:
</p>

<ul>
<li>
		<a href="https://access.redhat.com/downloads/content/69/ver=/rhel---7/7.0/x86_64/packages" rel="external nofollow">redhat.com</a>
	</li>
	<li>
		<a href="http://rpmfind.net" rel="external nofollow">rpmfind.net</a>.
	</li>
	<li>
		<a href="http://rpm.pbone.net/" rel="external nofollow">rpm.pbone.net</a>
	</li>
	<li>
		<a href="http://www.rpmseek.com" rel="external nofollow">rpmseek.com</a>
	</li>
</ul>
<p>
	يقدّم هذا المقال أمثلة لأوامر RPM من أجل المساعدة في تثبيت البرامج، تحديثها أو حذفها على توزيعة تستخدم RPM للتحزيم.
</p>

<p>
	<strong>ملحوظة:</strong> يجب أن تكون لديك صلاحيات الجذر حتى تستطيع إدارة الحزم.
</p>

<ol>
<li>
		<p>
			التحقق من توقيع حزمة
		</p>

		<p>
			يجب أولا التحقّق من مصدر الحزمة وموثوقيتها قبل تثبيتها. يُستخدم الخيار <code>checksig--</code> مع الأمر <code>rpm</code> لهذا الغرض. لكي نستطيع التحقق من حزمة فإنه يجب أولا استيراد المفاتيح العمومية Public keys الخاصّة بالنظام الذي نعمل عليه (Fedora، CentOS، RHEL أو غيرها). بالنسبة لتوزيعة Red Hat Enterprise Linux فالأمر على النحو التالي:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_3265_7">
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-*
</pre>

		<p>
			نطلب في الأمر التالي التحقق من الحزمة <code>pidgin-1.5.1-6.el3.x86_64.rpm</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_9">
[root@academy1 ~]# rpm --checksig pidgin-1.5.1-6.el3.x86_64.rpm 
pidgin-1.5.1-6.el3.x86_64.rpm: (sha1) dsa sha1 md5 gpg OK</pre>

		<p>
			لاحظ أن نتيجة التحقق هي <code>OK</code>.
		</p>
	</li>
	<li>
		<p>
			تثبيت حزمة
		</p>

		<p>
			يطلُب الأمر التالي تثبيت الحزمة <code>pidgin-1.5.1-6.el3.x86_64.rpm</code> التي تحققنا من موثوقيتها أعلاه:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_11">
[root@academy1 ~]# rpm -ivh pidgin-1.5.1-6.el3.x86_64.rpm
Preparing...                ########################################### [100%]
1:pidgin                 ########################################### [100%]</pre>

		<p>
			تظهر في الأمر أعلاه الخيارات التالية:
		</p>

		<ul>
<li>
				<code>i-</code>: وضع التثبيت،
			</li>
			<li>
				<code>v-</code>: طلب إظهار رسائل بتقدم عملية التثبيت،
			</li>
			<li>
				<code>h-</code>: طلب إظهار علامات <code>#</code> للدلالة على التقدم الحاصل في تنفيذ خطوات التثبيت.
			</li>
		</ul>
<p>
			الخياران الأخيران <code>v-</code> و<code>h-</code> ليسا ضروريين.
		</p>
	</li>
	<li>
		<p>
			التحقق من اعتماديات حزمة قبل تثبيتها
		</p>

		<p>
			تتيح أداة <code>rpm</code> التحقق من اعتماديات حزمة قبل تثبيتها، مثلا للتحقق من اعتماديات الحزمة <code>pidgin-2.11.0-1.fc24.x86_64.rpm</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_13">
[root@academy1 ~]# rpm -qpR pidgin-1.5.1-6.el3.x86_64.rpm
/bin/sh
/bin/sh
glib2 &gt;= 2.2
htmlview
libICE.so.6()(64bit)
libSM.so.6()(64bit)
libX11.so.6()(64bit)
libXext.so.6()(64bit)
libao.so.2()(64bit)
libatk-1.0.so.0()(64bit)
libaudiofile.so.0()(64bit)
(...)</pre>

		<p>
			يشير الخيار <code>q-</code> إلى أننا في وضع الاستعلام عن الحزمة. يطلب الخيار <code>p-</code> معلومات عن حزمة غير مثبّتة ويسرُد الخيار <code>R-</code> اعتماديّات الحزمة.
		</p>
	</li>
	<li>
		<p>
			تثبيت حزمة بغض النظر عن اعتمادياته
		</p>

		<p>
			لا يقبل <code>rpm</code> في الحالة العادية تثبيت حزمة إلا إذا كانت جميع اعتمادياتها مثبتة؛ إلا أنه يمكن إجباره على ذلك باستخدام الخيار <code>nodeps--</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_15">
[root@academy1 ~]# rpm -ivh --nodeps pidgin-1.5.1-6.el3.x86_64.rpm
Preparing...                          ################################# [100%]
Updating / installing...
1:pidgin-1.5.1-6.el3             ################################# [100%]</pre>

		<p>
			يُثبّت الأمر أعلاه الحزمة بتجاهل الأخطاء المتعلقة باعتماديّاتها؛ إلا أن البرنامج لن يعمل إلا بعد تثبيت الاعتماديات المطلوبة.
		</p>
	</li>
	<li>
		<p>
			التحقق من أن حزمة مثبّتة
		</p>

		<p>
			استخدم وضع الاستعلام <code>q-</code> للتأكد من أن حزمة مّا مثبتة على النظام:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_17">
[root@academy1 ~]# rpm -q BitTorrent
package BitTorrent is not installed
[root@academy1 ~]# rpm -q pidgin
pidgin-1.5.1-6.el3.x86_64.rpm</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد قائمة بجميع ملفات حزمة مثبتة
		</p>

		<p>
			أضف خيار السرد <code>l-</code> إلى وضع الاستعلام <code>q-</code> للحصول على قائمة بملفات حزمة مثبتة على النظام:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_19">
[root@academy1 ~]# rpm -ql pidgin
/etc/gconf/schemas/purple.schemas
/usr/bin/gaim
/usr/bin/pidgin
/usr/lib64/pidgin
/usr/lib64/pidgin/convcolors.so
/usr/lib64/pidgin/extplacement.so
/usr/lib64/pidgin/gestures.so
/usr/lib64/pidgin/gtkbuddynote.so
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد الحزم المُثبتة
		</p>

		<p>
			يسرُد الخيار <code>a-</code> عند استخدامه في وضع الاستعلام قائمة بأسماء جميع الحزم المثبتة:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_21">
[root@academy1 ~]# rpm -qa
libsss_nss_idmap-1.13.0-40.el7_2.9.x86_64
pygobject3-base-3.14.0-3.el7.x86_64
libfprint-0.5.0-3.el7.x86_64
man-pages-3.53-5.el7.noarch
redhat-release-server-7.2-9.el7.x86_64
rsyslog-7.4.7-12.el7.x86_64
libsane-hpaio-3.13.7-6.el7_2.1.x86_64
(...)</pre>

		<p>
			يمكن ترتيب القائمة لتظهر الحزم المثبتة مؤخرا في الأعلى باستخدام الخيار <code>last--</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_23">
[root@academy1 ~]# rpm -qa --last
pidgin-1.5.1-6.el3.x86_64.rpm                   Sun 04 Sep 2016 09:47:32 PM GMT
glibc-devel-2.17-106.el7_2.8.x86_64           Tue 02 Aug 2016 11:42:29 PM GMT
nss-pam-ldapd-0.8.13-8.el7.x86_64             Tue 02 Aug 2016 11:42:23 PM GMT
nscd-2.17-106.el7_2.8.x86_64                  Tue 02 Aug 2016 11:42:17 PM GMT
glibc-headers-2.17-106.el7_2.8.x86_64         Tue 02 Aug 2016 11:42:14 PM GMT
glibc-common-2.17-106.el7_2.8.x86_64          Tue 02 Aug 2016 11:42:01 PM GMT
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تحديث حزمة
		</p>

		<p>
			يُستخدَم وضع الترقية <code>U-</code> لتحديث إصدار حزمة مثبتة. يحتفظ أمر <code>rpm</code> عند تحديث حزمة بنسخة احتياطية من الإصدار المثبت للعودة إليها في حال لم تعمل الحزمة حسب المطلوب بعد تحديثها:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_25">
[root@academy1 ~]# rpm -Uvh pidgin-1.5.1-6.el3.x86_64.rpm
Preparing...                ########################################### [100%]
1:pidgin                     ########################################### [100%]</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			حذف حزمة
		</p>

		<p>
			استخدم الخيار <code>e-</code> مع الأمر <code>rpm</code> لحذف حزمة بذكر اسمها. مثلا؛ لحذف حزمة <code>pidgin</code> السابقة:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_3265_27">
[root@academy1 ~]# rpm -e pidgin
</pre>

		<p>
			تمكن أيضا إضافة الخيار <code>v </code>إلى الأمر لعرض رسائل بما يحدُث:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_29">
[root@academy1 ~]# rpm -ev pidgin
Preparing packages...
pidgin-1.5.1-6.el3.x86_64.rpm</pre>

		<p>
			كما يمكن الإبقاء على اعتماديات الحزمة باستخدام الخيار <code>nodeps--</code> مع أمر الحذف وهو ما ينتج عنه حذف الحزمة فقط دون اعتمادياتها:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_3265_31">
[root@academy1 ~]# rpm -ev --nodeps pidgin
</pre>

		<p>
			انتبه إلى أن حذف حزمة من النظام يمكن أن يؤدي إلى عدم استقراره؛ لذا تأكد من حاجتك فعلا لحذف الحزمة.
		</p>
	</li>
	<li>
		<p>
			معرفة الحزمة التي ينتمي إليها ملف
		</p>

		<p>
			استخدم الخيار <code>f-</code> في وضع الاستعلام لمعرفة الحزمة التي ينتمي إليها ملف. مثلا؛ تخبرنا نتيجة الأمر التالي أن الملف <code>usr/bin/htpasswd/</code> ينتمي للحزمة <code>httpd-tools-2.4.6-40.el7_2.4.x86_64</code>.
		</p>

		<pre class="ipsCode" id="ips_uid_3265_33">
[root@academy1 ~]# rpm -qf /usr/bin/htpasswd
httpd-tools-2.4.6-40.el7_2.4.x86_64</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			الحصول على معلومات عن حزمة
		</p>

		<p>
			يعرض الخيار <code>i-</code> عند استخدامه في وضع الاستعلام معلومات عن حزمة مثبتة؛ مثلا بالنسبة لحزمة <a href="https://academy.hsoub.com/certificates/redhat/rhcsa/%d8%a5%d8%b9%d8%af%d8%a7%d8%af-%d8%ae%d8%a7%d8%af%d9%88%d9%85-%d9%88%d9%90%d8%a8-%d9%88%d8%ae%d8%a7%d8%af%d9%88%d9%85-ftp-%d8%b9%d9%84%d9%89-red-hat-enterprise-linux-r48/#%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-ftp-%D9%88%D8%AA%D8%A3%D9%85%D9%8A%D9%86%D9%87" rel=""><code>vsftpd</code></a>:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_41">
[root@academy1 ~]# rpm -qi vsftpd
Name        : vsftpd
Version     : 3.0.2
Release     : 11.el7_2
Architecture: x86_64
Install Date: Thu 21 Jul 2016 03:29:37 PM GMT
Group       : System Environment/Daemons
Size        : 355788
License     : GPLv2 with exceptions
Signature   : RSA/SHA256, Fri 18 Mar 2016 01:08:35 AM GMT, Key ID 199e2f91fd431d51
Source RPM  : vsftpd-3.0.2-11.el7_2.src.rpm
Build Date  : Wed 24 Feb 2016 11:06:41 AM GMT
Build Host  : x86-019.build.eng.bos.redhat.com
Relocations : (not relocatable)
Packager    : Red Hat, Inc. &lt;http://bugzilla.redhat.com/bugzilla&gt;
Vendor      : Red Hat, Inc.
URL         : https://security.appspot.com/vsftpd.html
Summary     : Very Secure Ftp Daemon
Description :
vsftpd is a Very Secure FTP daemon. It was written completely from scratch.</pre>

		<p>
			أما إن أردت الحصول على معلومات عن حزمة قبل تثبيتها فالأمر هو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_39">
[root@academy1 ~]# rpm -qip pidgin-1.5.1-6.el3.x86_64.rpm
Name        : pidgin
Version     : 1.5.1
Release     : 6.el3
Architecture: x86_64
Install Date: (not installed)
Group       : Applications/Internet
Size        : 11168813
License     : GPL
Signature   : DSA/SHA1, Thu 29 Oct 2009 08:14:44 AM GMT, Key ID 219180cddb42a60e
Source RPM  : pidgin-1.5.1-6.el3.src.rpm
Build Date  : Wed 28 Oct 2009 03:52:51 PM GMT
Build Host  : x86-003.build.bos.redhat.com
Relocations : (not relocatable)
Packager    : Red Hat, Inc. &lt;http://bugzilla.redhat.com/bugzilla&gt;
Vendor      : Red Hat, Inc.
URL         : http://www.pidgin/im/
Summary     : A Gtk+ based multiprotocol instant messaging client
Description :
Pidgin allows you to talk to anyone using a variety of messaging protocols, including AIM, ICQ, IRC, Yahoo!, Novell Groupwise, MSN Messenger, Jabber, Gadu-Gadu, Napster, and Zephyr.  These protocols are implemented using a modular, easy to use design. To use a protocol, just add an account using the account editor. Pidgin supports many common features of other clients, as well as many
unique features, such as perl scripting, TCL scripting and C plugins.

Pidgin is NOT affiliated with or endorsed by America Online, Inc., Microsoft Corporation, Yahoo! Inc., or ICQ Inc.
[root@academy1 ~]#</pre>

		<pre>
<code>


</code></pre>
	</li>
	<li>
		<p>
			الاستعلام عن التوثيق Documentation الخاص بحزمة مثبتة
		</p>

		<p>
			يمكن الحصول على مستندات التوثيق الخاصّة بحزمة باستخدام الخيارين <code>df-</code> في وضع الاستعلام. يأخذ الأمر معطى عبارة عن مسار الحزمة؛ وهو ما يمكن الحصول عليه عن طريق الأمر <code>which</code>. نطلب في المثال التالي معرفة مسار الحزمة <code>vsftpd</code> ثم نستعلم عن مستدات التوثيق الخاصّة بها:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_43">
[root@academy1 ~]# which vsftpd
/sbin/vsftpd
[root@academy1 ~]# rpm -qdf /sbin/vsftpd
/usr/share/doc/vsftpd-3.0.2/AUDIT
/usr/share/doc/vsftpd-3.0.2/BENCHMARKS
/usr/share/doc/vsftpd-3.0.2/BUGS
/usr/share/doc/vsftpd-3.0.2/COPYING
/usr/share/doc/vsftpd-3.0.2/Changelog
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			التحقق من حزمة
		</p>

		<p>
			تقارن أداة <code>rpm</code> عند طلب التحقق من حزمة المعلومات المستقاة من الملفات المثبتة مع تلك الموجودة في قاعدة بيانات <code>rpm</code>. يُستخدم الخيار <code>V-</code> لوضع التحقق و<code>p</code> لتمرير حزمة إلى الأمر:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_45">
[root@academy1 ~]# rpm -Vp vsftpd-3.0.3-2.fc24.x86_64.rpm 
warning: vsftpd-3.0.3-2.fc24.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 81b46521: NOKEY
.......T.  c /etc/logrotate.d/vsftpd
.......T.  c /etc/pam.d/vsftpd
.......T.  c /etc/vsftpd/ftpusers
.......T.  c /etc/vsftpd/user_list
.......T.  c /etc/vsftpd/vsftpd.conf
.......T.    /etc/vsftpd/vsftpd_conf_migrate.sh
.......T.    /usr/lib/systemd/system-generators/vsftpd-generator
.......T.    /usr/lib/systemd/system/vsftpd.service
.......T.    /usr/lib/systemd/system/vsftpd.target
.......T.    /usr/lib/systemd/system/vsftpd@.service
S.5....T.    /usr/sbin/vsftpd
missing     /usr/share/doc/vsftpd
missing   d /usr/share/doc/vsftpd/AUDIT
missing   d /usr/share/doc/vsftpd/BENCHMARKS
missing   d /usr/share/doc/vsftpd/BUGS
(...)</pre>

		<p>
			يمكن طلب التحقق من جميع الحزم في النظام بالخيار <code>a</code> في وضع التحقق على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_48">
[root@academy1 ~]# rpm -Va
S.5....T.  c /etc/os-release
S.5....T.    /usr/src/kernels/3.10.0-327.22.2.el7.x86_64/include/config/auto.conf
S.5....T.    /usr/src/kernels/3.10.0-327.22.2.el7.x86_64/include/config/auto.conf.cmd
S.5....T.    /usr/src/kernels/3.10.0-327.22.2.el7.x86_64/include/config/tristate.conf
S.5....T.    /usr/src/kernels/3.10.0-327.22.2.el7.x86_64/include/generated/autoconf.h
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد جميع المفاتيح العمومية المستوردة
		</p>

		<p>
			يمكنك إن أردت سرد جميع المفاتيح العمومية للحزم المثبتة على نظامك، وذلك على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_50">
[root@academy1 ~]# rpm -qa gpg-pubkey*
gpg-pubkey-2fa658e0-45700c69
gpg-pubkey-37017186-45761324
gpg-pubkey-897da07a-3c979a7f
gpg-pubkey-f21541eb-4a5233e7
gpg-pubkey-42193e6b-4624eff2
gpg-pubkey-fd431d51-4ae0493b
gpg-pubkey-db42a60e-37ea5438</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تصحيح قاعدة بيانات RPM معطوبة
		</p>

		<p>
			يحدُث أن تُصاب قاعدة البيانات الخاصّة بحزم RPM بعُطب مما ينتُج عنه غياب وظائف من أداة <code>rpm</code>. يمكنك في هذه الحالة محاولة بناء قاعدة البيانات من جديد بالأوامر التالية:
		</p>

		<pre class="ipsCode" id="ips_uid_3265_52">
[root@academy1 ~]# cd /var/lib/rpm
[root@academy1 rpm]# rm __db*
[root@academy1 rpm]# rpm --rebuilddb
[root@academy1 rpm]# /usr/lib/rpm/rpmdb_verify Packages
BDB5105 Verification of Packages succeeded.</pre>

		<p>
			 
		</p>
	</li>
</ol>
<p>
	ترجمة - وبتصرف - لمقال <a href="http://www.tecmint.com/20-practical-examples-of-rpm-commands-in-linux/" rel="external nofollow">20 Practical Examples of RPM Commands in Linux</a> لصاحبه Ravi Saive.
</p>
]]></description><guid isPermaLink="false">283</guid><pubDate>Tue, 22 Nov 2016 11:15:00 +0000</pubDate></item><item><title>&#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x62E;&#x62F;&#x645;&#x627;&#x62A; &#x639;&#x644;&#x649; &#x644;&#x64A;&#x646;&#x643;&#x633; &#x628;&#x623;&#x62F;&#x648;&#x627;&#x62A; &#x646;&#x638;&#x627;&#x645; &#x627;&#x644;&#x62A;&#x645;&#x647;&#x64A;&#x62F; systemd</title><link>https://academy.hsoub.com/devops/linux/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AE%D8%AF%D9%85%D8%A7%D8%AA-%D8%B9%D9%84%D9%89-%D9%84%D9%8A%D9%86%D9%83%D8%B3-%D8%A8%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D9%85%D9%87%D9%8A%D8%AF-systemd-r284/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_12/systemd.png.e888681d6e6e20a2a94c0d39adaf4711.png" /></p>

<p>
	يتكوّن نظام التمهيد <a href="https://academy.hsoub.com/tags/systemd/" rel="">systemd</a> من مجموعة من الأدوات التي تمثّل منصة مركزية لإدارة نظام لينكس وإعداده. تُستخدم أداة <code>systemctl</code> للتحكّم في systemd وإدارة الخدمات المرتبطة به. يهدف هذا المقال إلى إلقاء الضوء على كيفية إدارة النظام والخدمات على نظام تشغيل يستخدم systemd للتمهيد.
</p>

<h2 id="أساسيات-systemd-وsystemctl">
	أساسيات systemd وsystemctl
</h2>

<ol>
<li>
		<p>
			التحقق من أن <code>systemd</code> مثبّت وإصداره:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_2399_7">
$ systemd --version
systemd 229
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN
</pre>

		<p>
			يظهر من المثال أعلاه أن نظام التمهيد <code>systemd</code> مثبت وأن لدينا الإصدار <code>229</code>.
		</p>
	</li>
	<li>
		<p>
			التحقق من مكان تواجد الملفات التنفيذية والمكتبات البرمجية الخاصّة بـ و<code>systemctl</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_9">
$ whereis systemd
systemd: /usr/lib/systemd /bin/systemd /etc/systemd /lib/systemd /usr/share/systemd /usr/share/man/man1/systemd.1.gz
$ whereis systemctl
systemctl: /bin/systemctl /usr/share/man/man1/systemctl.1.gz</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			التحقق من حالة عمل systemd
		</p>

		<p>
			يمكن استخدام الأمر <code>ps</code> لسرد العمليات Processes النشطة ثم عزل تلك المتعلقة بـ<code>systemd</code>، وذلك على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_11">
$ ps -eaf | grep [s]ystemd
root      1000     1  0 12:23 ?        00:00:00 /lib/systemd/systemd-journald
root      1029     1  0 12:23 ?        00:00:00 /lib/systemd/systemd-udevd
systemd+  2639     1  0 12:23 ?        00:00:00 /lib/systemd/systemd-timesyncd
message+  2781     1  0 12:23 ?        00:00:01 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root      2862     1  0 12:23 ?        00:00:00 /lib/systemd/systemd-logind
sddm      3284     1  0 12:23 ?        00:00:00 /lib/systemd/systemd --user
academy   3532     1  0 12:25 ?        00:00:00 /lib/systemd/systemd --user</pre>

		<p>
			تحمل عمليّة <code>systemd</code> المعرِّف <code>1</code>. استخدمنا الخيار <code>e-</code> <a href="https://academy.hsoub.com/devops/linux/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-process-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%B7%D8%B1%D9%81%D9%8A%D8%A9-r70/" rel="">مع الأمر <code>ps</code></a> لسرد جميع العمليات، ثم حدّدنا العمليات التي لا ترأس جلسة Session leaders (العمليات التي يساوي معرّف العمليّة السّلف Parent Id معرّفَ الجلسة Session Id). استخدمنا الخيار <code>f-</code> لتهيئة مخرجات الأمر التي طبّقنا عليه الأمر <code>grep</code> لتحديد تلك التي توافق <a href="https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-regular-expressions-r63/" rel="">التعبير النمطي</a> <code>s]ystemd]</code>.
		</p>
	</li>
	<li>
		<p>
			تحليل متتالية الإقلاع في systemd
		</p>

		<p>
			تُستخدَم أداة <code>systemd-analyze</code> لتحليل متتالية الإقلاع:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_13">
$ systemd-analyze 
Startup finished in 9.314s (firmware) + 2.897s (loader) + 9.290s (kernel) + 46.672s (userspace) = 1min 8.175s</pre>

		<p>
			نضيف المعطى <code>blame</code> للأمر أعلاه من أجل الحصول على الوقت الذي استغرقته كل خدمة للإقلاع:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_15">
$ systemd-analyze blame
    40.880s systemd-suspend.service
    25.010s apt-daily.service
    14.173s dev-sda7.device
    10.530s dnsmasq.service
    10.228s click-system-hooks.service
    7.909s accounts-daemon.service
    7.908s ModemManager.service
    7.120s NetworkManager-wait-online.service
    7.084s gpu-manager.service
    (...)</pre>

		<p>
			يمكن أيضا تحليل الوقت المستغرق للعمليات الحرجة باستخدام المعطى <code>critical-chain</code> الذي يطبع شجرة بتتالي العمليات التي تنتظر بقية العمليات إقلاعها:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_17">
$ systemd-analyze critical-chain
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

graphical.target @41.348s
└─multi-user.target @41.348s
└─apache2.service @34.735s +6.612s
    └─network-online.target @34.717s
    └─NetworkManager-wait-online.service @27.596s +7.120s
        └─NetworkManager.service @21.672s +5.913s
        └─dbus.service @21.471s
            └─basic.target @21.470s
            └─sockets.target @21.470s
                └─snapd.socket @21.441s +17ms
                └─sysinit.target @21.391s
                    └─apparmor.service @20.785s +605ms
                    └─local-fs.target @20.772s
                        └─run-user-123.mount @35.991s
                        └─local-fs-pre.target @15.110s
                            └─systemd-remount-fs.service @15.038s +27ms
                            └─systemd-journald.socket @3.530s
                                └─-.slice @3.497s</pre>

		<p>
			تظهر بعد علامة <code>@</code> المدة التي فُعلت بعدها <a href="https://academy.hsoub.com/devops/linux/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-systemd-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%AE%D8%AF%D9%85%D8%A7%D8%AA%D8%8C-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-units%D8%8C-%D9%88%D8%A7%D9%84%D9%8A%D9%88%D9%85%D9%8A%D8%A7%D8%AA-journal-r130#%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A9-%D8%A8%D8%B4%D9%83%D9%84-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A-Basic-Unit-Management" rel="">الوحدة</a>، في ما يظهر الوقت الذي استغرقته الوحدة للإقلاع بعد علامة <code>+</code>.
		</p>

		<p>
			يمكن تمرير اسم وحدة إلى الأمر أعلاه لقصر السّرد على العمليات التي تنتظر الوحدة إقلاعها:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_19">
$ systemd-analyze critical-chain apache2.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

└─network-online.target @35.533s
└─NetworkManager-wait-online.service @29.424s +6.108s
    └─NetworkManager.service @22.174s +7.234s
    └─dbus.service @20.998s
        └─basic.target @20.976s
        └─sockets.target @20.976s
            └─snapd.socket @20.919s +46ms
            └─sysinit.target @20.902s
                └─apparmor.service @19.691s +1.193s
                └─local-fs.target @19.681s
                    └─run-user-123.mount @37.402s
                    └─local-fs-pre.target @14.915s
                        └─systemd-remount-fs.service @14.866s +32ms
                        └─system.slice @3.541s
                            └─-.slice @3.508s</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد الوحدات
		</p>

		<p>
			يعمل الأمر <code>systemctl</code> عند استخدام المعطى <code>list-unit-files</code> على سرد قائمة بجميع الوحدات الموجودة في النظام:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_21">
$ systemctl list-unit-files
UNIT FILE                                  STATE   
proc-sys-fs-binfmt_misc.automount          static  
org.freedesktop.hostname1.busname          static  
org.freedesktop.locale1.busname            static  
org.freedesktop.login1.busname             static  
org.freedesktop.network1.busname           static  
org.freedesktop.resolve1.busname           static  
org.freedesktop.systemd1.busname           static  
org.freedesktop.timedate1.busname          static  
dev-hugepages.mount                        static  
dev-mqueue.mount                           static  
proc-sys-fs-binfmt_misc.mount              static  
sys-fs-fuse-connections.mount              static  
sys-kernel-config.mount                    static  
sys-kernel-debug.mount                     static  
acpid.path                                 enabled 
cups.path                                  enabled 
(...)</pre>

		<p>
			<strong>ملحوظة:</strong> يمكن للوحدة أن تكون خدمة، نقطة تركيب Mount point، مقبس شبكة Socket أو جهازا طرفيا Device.
		</p>

		<p>
			يمكنك الاقتصار على الوحدات العاملة حاليا بالمعطى <code>list-units</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_23">
$ systemctl list-units
UNIT LOAD ACTIVE SUB DESCRIPTION
proc-sys-fs-binfmt_misc.automount loaded active running Arbitrary Executable File Formats File System Automoun
sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\x2deDP\x2d1-intel_backlight.device loaded active plugged /sys/devices/pci0000:
sys-devices-pci0000:00-0000:00:03.0-sound-card0.device loaded active plugged Broadwell-U Audio Controller
sys-devices-pci0000:00-0000:00:14.0-usb1-1\x2d3-1\x2d3:1.0-net-enx582c80139263.device loaded active plugged E353/E3131
sys-devices-pci0000:00-0000:00:14.0-usb1-1\x2d4-1\x2d4:1.0-bluetooth-hci0.device loaded active plugged /sys/devices/pci0000:00/000
sys-devices-pci0000:00-0000:00:1b.0-sound-card1.device loaded active plugged Wildcat Point-LP High Definition Audio Controller
(…)</pre>

		<p>
			كما يمكن عزل الوحدات التي أخفقت بالمعطى <code>failed--</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_25">
$ systemctl --failed
UNIT                    LOAD   ACTIVE SUB    DESCRIPTION
● snapd.refresh.service   loaded failed failed Automatically refresh installed snaps
● systemd-suspend.service loaded failed failed Suspend

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

2 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			التحقق من تفعيل خدمة
		</p>

		<p>
			يطلُب الأمر التالي التحقق من أن خدمة <a href="https://academy.hsoub.com/search/?&amp;type=cms_records4&amp;tags=cron&amp;search_in=titles" rel="">الجدولة Cron</a> مفعَّلة (تعمل مع إقلاع النظام):
		</p>

		<pre class="ipsCode" id="ips_uid_2399_27">
$ systemctl is-enabled cron.service
enabled</pre>

		<p>
			يظهر من نتيجة الأمر أن الخدمة مفعَّلة <code>enabled</code>.
		</p>
	</li>
	<li>
		<p>
			التحقق من حالة خدمة
		</p>

		<p>
			نتحقق في الأمر التالي من حالة الخدمتين <code>mysql</code> و<code>apache2</code>:<br><script type="math/tex" id="MathJax-Element-4"> systemctl status mysql.service   
    ● mysql.service - MySQL Community Server  
    Loaded: loaded (/lib/systemd/system/mysql.service; disabled; vendor preset: enabled)  
    Active: inactive (dead)  
    </script></p>

		<pre class="ipsCode" id="ips_uid_2399_29">
systemctl status apache2.service
● apache2.service - LSB: Apache2 web server
Loaded: loaded (/etc/init.d/apache2; bad; vendor preset: enabled)
Drop-In: /lib/systemd/system/apache2.service.d
└─apache2-systemd.conf
Active: active (running) since Wed 2016-09-14 12:23:56 GMT; 4h 31min ago</pre>

		<p>
			يظهر في نتيجة تنفيذ الأمرين أعلاه أن <code>mysql</code> غير مفعَّلة وليست نشطة أثناء تنفيذ الأمر؛ أما الخدمة <code>apache2</code> فهي مفعَّلة وتعمل منذ أربع ساعات.
		</p>
	</li>
</ol>
<h2 id="التحكم-في-الخدمات-وإداراتها-بـ-systemctl">
	التحكم في الخدمات وإداراتها بـ systemctl
</h2>

<ol>
<li>
		<p>
			سرد جميع الخدمات
		</p>

		<p>
			يسرُد الأمر التالي جميع خدمات النظام بغضّ النظر عن حالتها (مفعَّلة أو معطَّلة):
		</p>

		<pre class="ipsCode" id="ips_uid_2399_31">
$ systemctl list-unit-files --type=service
UNIT FILE                                  STATE   
accounts-daemon.service                    enabled 
acpid.service                              disabled
apport-forward@.service                    static  
apt-daily.service                          static  
atd.service                                enabled 
autovt@.service                            enabled 
bootlogd.service                           masked  
bootlogs.service                           masked  
bootmisc.service                           masked  
cgmanager.service                          enabled 
cgproxy.service                            enabled 
checkfs.service                            masked  
checkroot-bootclean.service                masked  
checkroot.service                          masked  
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تشغيل خدمة (apache2)، إيقافها، إعادة تشغيلها أو إعادة تحميلها:
		</p>

		<p>
			تبدأ الأوامر التالية تشغيل الخدمة <code>apache2</code>، تعيد تحميلها، تعيد تشغيلها وتوقفها على التوالي (تحتاج لصلاحيات إدارية):
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_2399_34">
# sudo systemctl start apache2
# sudo systemctl restart apache2
# sudo systemctl stop apache2
# sudo systemctl reload apache2
apache2.service is not active, cannot reload.
# sudo systemctl start apache2
# sudo systemctl reload apache2
# sudo systemctl status  apache2
● apache2.service - LSB: Apache2 web server
Loaded: loaded (/etc/init.d/apache2; bad; vendor preset: enabled)
Drop-In: /lib/systemd/system/apache2.service.d
        └─apache2-systemd.conf
Active: active (running) since Wed 2016-09-14 17:15:11 GMT; 17s ago
</pre>

		<p>
			لا تُظهر الأوامر أعلاه مخرجات عند تنفيذها بدون مشاكل. استخدم أمر التحقق <code>status</code> لمعرفة حالة الخدمة.
		</p>
	</li>
	<li>
		<p>
			تفعيل خدمة أو تعطيلها
		</p>

		<p>
			تُسمّى الخدمات التي تبدأ بالعمل مع إقلاع النظام بالخدمات المفعَّلة Enabled، وعكسُها الخدمات المعطّلة Disabled. أما الخدمات النشطة Active فهي الخدمات العاملة حاليا (تُشغَّل بالأمر <code>start</code>). يستفسر الأمر التالي عن نشاط الخدمة <code>apache2</code> (تعمل أم لا):
		</p>

		<pre class="ipsCode" id="ips_uid_2399_36">
$ systemctl is-active apache2.service 
active</pre>

		<p>
			نستخدم الأمر <code>disable</code> لتعطيل خدمة و<code>enable</code> لتفعيلها:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_38">
# systemctl enable apache2.service 
# systemctl disable apache2.service</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			إخفاء خدمة
		</p>

		<p>
			يمنع الإخفاء Masking تشغيل خدمة. يمكن إخفاء الخدمة <code>apache2</code> على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_40">
# systemctl mask apache2.service 
Created symlink from /etc/systemd/system/apache2.service to /dev/null.</pre>

		<p>
			ولإلغاء الإخفاء:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_44">
$ sudo systemctl unmask apache2.service 
Removed symlink /etc/systemd/system/apache2.service.</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			الإيقاف الإجباري لخدمة بـsystemctl
		</p>

		<pre class="ipsCode" id="ips_uid_2399_62">
# systemctl kill apache2
# sudo systemctl status apache2
● apache2.service - LSB: Apache2 web server
Loaded: loaded (/etc/init.d/apache2; bad; vendor preset: enabled)
Drop-In: /etc/systemd/system/apache2.service.d
        └─50-CPUShares.conf
        /lib/systemd/system/apache2.service.d
        └─apache2-systemd.conf
Active: inactive (dead)
    Docs: man:systemd-sysv-generator(8)</pre>

		<p>
			 
		</p>
	</li>
</ol>
<h2 id="التحكم-في-نقاط-التركيب-وإداراتها-بـsystemctl">
	التحكم في نقاط التركيب وإداراتها بـsystemctl
</h2>

<ol>
<li>
		<p>
			سرد جميع نقاط التركيب في النظام
		</p>

		<pre class="ipsCode" id="ips_uid_2399_64">
$ systemctl list-unit-files --type=mount
UNIT FILE                     STATE 
dev-hugepages.mount           static
dev-mqueue.mount              static
proc-sys-fs-binfmt_misc.mount static
sys-fs-fuse-connections.mount static
sys-kernel-config.mount       static
sys-kernel-debug.mount        static
tmp.mount                     disabled

7 unit files listed.</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			إدارة نقاط التركيب
		</p>

		<p>
			يمكن بالأوامر التالية تشغيل نقطة تركيب، فصلها، إعادة تركيبها والتحقق من حالتها على التوالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_66">
# systemctl start tmp.mount
# systemctl stop tmp.mount
# systemctl restart tmp.mount
# systemctl reload tmp.mount
# systemctl status tmp.mount
tmp.mount - Temporary Directory
Loaded: loaded (/usr/lib/systemd/system/tmp.mount; disabled)
Active: active (mounted) since Wed 2016-09-14 17:36:11 GMT;; 2min 48s ago
Where: /tmp
What: tmpfs
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تفعيل نقطة تركيب أو تعطيلها
		</p>

		<p>
			يمكن بطريقة مشابهة للخدمات تفعيل نقاط التركيب أوتعطيلها:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_68">
# systemctl enable tmp.mount
# systemctl disable  tmp.mount</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			إخفاء نقطة تركيب
		</p>

		<p>
			يُستخدَم الأمر <code>mask</code> لإخفاء نقطة تركيب على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_70">
# systemctl mask tmp.mount
Created symlink from /etc/systemd/system/tmp.mount to /dev/null.</pre>

		<p>
			ولإلغاء الإخفاء:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_72">
# systemctl unmask tmp.mount
Removed symlink /etc/systemd/system/tmp.mount</pre>

		<p>
			 
		</p>
	</li>
</ol>
<h2 id="التحكم-في-مقابس-الشبكة-بـsystemctl">
	التحكّم في مقابس الشبكة بـsystemctl
</h2>

<ol>
<li>
		<p>
			سرد جميع المقابس
		</p>

		<pre class="ipsCode" id="ips_uid_2399_76">
$ systemctl list-unit-files --type=socket
UNIT FILE                       STATE   
acpid.socket                    enabled 
apport-forward.socket           enabled 
avahi-daemon.socket             enabled 
cups.socket                     enabled 
dbus.socket                     static  
lxd.socket                      masked  
saned.socket                    disabled
snapd.socket                    enabled 
syslog.socket                   static  
systemd-bus-proxyd.socket       static  
systemd-fsckd.socket            static  
systemd-initctl.socket          static  
systemd-journald-audit.socket   static  
systemd-journald-dev-log.socket static  
systemd-journald.socket         static  
systemd-networkd.socket         disabled
systemd-rfkill.socket           static  
systemd-udevd-control.socket    static  
systemd-udevd-kernel.socket     static  
uuidd.socket                    enabled                                                                                               
20 unit files listed.</pre>

		<pre>
<code>

</code></pre>
	</li>
	<li>
		<p>
			تشغيل مقبس (cups)، إعادة تشغيله، إعادة تحميله أو إيقافه:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_78">
# systemctl start cups.socket
# systemctl restart cups.socket
# systemctl reload cups.socket
# systemctl stop cups.socket
$ systemctl status cups.socket
● cups.socket - CUPS Scheduler
Loaded: loaded (/lib/systemd/system/cups.socket; enabled; vendor preset: enabled)
Active: active (listening) since Thu 2016-09-15 14:39:47 GMT; 5s ago
Listen: /var/run/cups/cups.sock (Stream)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تفعيل مقبس أو تعطيله:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_80">
# systemctl enable cups.socket
# systemctl disable cups.socket</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			إخفاء مقبس
		</p>

		<pre class="ipsCode" id="ips_uid_2399_82">
$ sudo systemctl mask cups.socket
Created symlink from /etc/systemd/system/cups.socket to /dev/null.
$ sudo systemctl unmask cups.socket
Removed symlink /etc/systemd/system/cups.socket.</pre>

		<p>
			 
		</p>
	</li>
</ol>
<h2 id="استخدام-المعالج">
	استخدام المعالج
</h2>

<ol>
<li>
		<p>
			حصة خدمة من المعالج
		</p>

		<p>
			يمكن استخدام <code>systemctl</code> لعرض عدد الحصص الحاليّة المحدّدة لخدمة من المعالج:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_84">
# systemctl show -p CPUShares apache2.service
CPUShares=18446744073709551615</pre>

		<p>
			تعرّف قيمة <code>CPUShares</code> الوقت المخصّص للخدمة من المعالج. تعني زيادة هذه القيمة الرفع من أولويّة للخدمة. يمكن تحديد الحصّة بتغيير قيمة المتغيّر على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_86">
# systemctl set-property apache2.service CPUShares=1500
$ systemctl show -p CPUShares apache2.service
CPUShares=1500</pre>

		<p>
			ينشئ النظام عند تحديد حصّة خدمة مجلّدا يوافق اسمه اسمَ الخدمة (مثلا <code>apache2.service.d</code>) وينشئ بداخله ملف إعداد يبدأ برقم يتبعه اسم المتغيّر (مثلا <code>50-CPUShares.conf</code>):
		</p>

		<pre class="ipsCode" id="ips_uid_2399_88">
$ cat /etc/systemd/system/apache2.service.d/50-CPUShares.conf 
[Service]
CPUShares=1500</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			عرض تفاصيل الإعداد الخاصّة بخدمة
		</p>

		<pre class="ipsCode" id="ips_uid_2399_90">
$ systemctl show apache2
Type=forking
Restart=no
NotifyAccess=none
RestartUSec=100ms
TimeoutStartUSec=5min
TimeoutStopUSec=5min
RuntimeMaxUSec=infinity
WatchdogUSec=0
WatchdogTimestampMonotonic=0
FailureAction=none
PermissionsStartOnly=no
RootDirectoryStartOnly=no
RemainAfterExit=no
GuessMainPID=no
MainPID=0
ControlPID=0
FileDescriptorStoreMax=0
NFileDescriptorStore=0
StatusErrno=0
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			عرض اعتماديّات خدمة
		</p>

		<pre class="ipsCode" id="ips_uid_2399_92">
$ systemctl list-dependencies apache2.service
apache2.service
● ├─system.slice
● ├─network-online.target
● │ ├─networking.service
● │ └─NetworkManager-wait-online.service
● └─sysinit.target
●   ├─apparmor.service
●   ├─brltty.service
●   ├─console-setup.service
●   ├─dev-hugepages.mount
●   ├─dev-mqueue.mount
●   ├─friendly-recovery.service
●   ├─keyboard-setup.service
●   ├─kmod-static-nodes.service
●   ├─plymouth-read-write.service
●   ├─plymouth-start.service
●   ├─proc-sys-fs-binfmt_misc.automount
●   ├─resolvconf.service
●   ├─setvtrgb.service
(...)</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد مجموعات التحكّم Control groups
		</p>

		<p>
			يُستخدَم الأمر <code>systemd-cgls</code> لسرد مجموعات التحكّم هرميّا على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_94">
# systemd-cgls
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
├─user.slice
│ └─user-1000.slice
│   └─session-1.scope
│     ├─ 2292 gdm-session-worker [pam/gdm-password]
│     ├─ 2308 /usr/bin/gnome-keyring-daemon --daemonize --login
│     ├─ 2351 gnome-session --session gnome-classic
│     ├─ 2358 dbus-launch --sh-syntax --exit-with-session
│     ├─ 2359 /bin/dbus-daemon --fork --print-<abbr title="Process IDentifier | معرّف العملية أو البرنامج">pid</abbr> 4 --print-address 6 --sessi...
│     ├─ 2424 /usr/libexec/gvfsd
│     ├─ 2428 /usr/libexec/gvfsd-fuse /run/user/1000/gvfs -f -o big_writes</pre>

		<p>
			يُمكن سرد هذه المجموعات حسب استخدام المعالج والذاكرة العشوائية أو حسب المُدخَلات والمُخرجات بالأمر <code>systemd-cgtop</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_96">
Path                                              Tasks   %CPU   Memory  Input/s Output/s

/                                                  216   37.7     1.6G        -        -
/system.slice                                      -    7.1        -        -        -
/system.slice/gdm.service                          2    7.1        -        -        -
/system.slice/rngd.service                         1    0.0        -        -        -
/system.slice/tuned.service                        1    0.0        -        -        -
/system.slice/vboxadd-service.service              1    0.0        -        -        -
/system.slice/httpd.service                        6    0.0        -        -        -</pre>

		<p>
			 
		</p>
	</li>
</ol>
<h2 id="التحكم-في-مستويات-التشغيل-runlevels">
	التحكم في مستويات التشغيل Runlevels
</h2>

<ol>
<li>
		<p>
			الإقلاع في وضع الإنقاذ Rescue mode أو وضع الطوارئ Emergency mode
		</p>

		<p>
			يمكن في حال حدوث مشكل الإقلاعُ في وضع الإنقاذ بالأمر التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_98">
# systemctl rescue</pre>

		<p>
			كما يُستخدم الأمر <code>systemctl</code> للإقلاع في وضع الطوارئ:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_100">
# systemctl emergency</pre>

		<p>
			وللعودة إلى وضع الإقلاع المبدئي:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_102">
# systemctl default</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			عرض مستوى التشغيل الحالي
		</p>

		<pre class="ipsCode" id="ips_uid_2399_104">
$ systemctl get-default
graphical.target</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			الإقلاع على مستوى تشغيل
		</p>

		<p>
			يمكن تحديد مستوى التشغيل الذي نريد الإقلاع عليه بالأمر <code>systemctl isolate</code>؛ مثلا:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_106">
# systemctl isolate runlevel5.target
# systemctl isolate runlevel3.target</pre>

		<p>
			أو بذكر اسم المستوى:
		</p>

		<pre class="ipsCode" id="ips_uid_2399_108">
# systemctl isolate graphical.target
# systemctl isolate multiuser.target</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تعيين مستوى التشغيل المبدئي
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_2399_110">
# systemctl set-default runlevel3.target
# systemctl set-default runlevel5.target
</pre>

		<p>
			مستويات التشغيل هي التالية:
		</p>

		<ul style="margin-right: 40px;">
<li>
				المستوى 0 <code>runlevel0</code>: إيقاف تشغيل النظام وفصله عن الطاقة.
			</li>
			<li>
				المستوى 1 <code>runlevel1</code>: وضع الإنقاذ والصيانة.
			</li>
			<li>
				المستوى 2 <code>runlevel2</code>: تعدّد المستخدمين.
			</li>
			<li>
				المستوى 3 <code>runlevel3</code>: تعدّد المستخدمين مع تشغيل خدمات الشبكة.
			</li>
			<li>
				المستوى 4 <code>runlevel4</code>: مستوى تشغيل محجوز لما يعرّفه المستخدم.
			</li>
			<li>
				المستوى 5 <code>runlevel5</code>: المستوى 3 + واجهة رسومية.
			</li>
			<li>
				المستوى 6 <code>runlevel6</code>: إعادة تشغيل النظام.
			</li>
		</ul>
</li>
	<li>
		إعادة تشغيل النظام، إيقافه، تعليقه وإسباته
	</li>
</ol>
<pre class="ipsCode" id="ips_uid_5545_9">
# systemctl reboot
# systemctl halt
# systemctl suspend
# systemctl hibernate</pre>

<p style="margin-right: 40px;">
	كما يمكن جعل النظام في وضع السبات المزدوج (مزيج من وضع السبات والتعليق) بالأمر:
</p>

<p>
	 
</p>

<pre class="ipsCode" id="ips_uid_7323_9">
# systemctl hybrid-sleep</pre>

<p>
	ترجمة - بتصرّف - لمقال <a href="http://www.tecmint.com/manage-services-using-systemd-and-systemctl-in-linux" rel="external nofollow">How to Manage ‘Systemd’ Services and Units Using ‘Systemctl’ in Linux</a>.
</p>
]]></description><guid isPermaLink="false">284</guid><pubDate>Tue, 01 Nov 2016 10:11:00 +0000</pubDate></item><item><title>18 &#x645;&#x62B;&#x627;&#x644;&#x627; &#x644;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x62F;&#x64A;&#x631; &#x627;&#x644;&#x62D;&#x632;&#x645; YUM</title><link>https://academy.hsoub.com/devops/linux/18-%D9%85%D8%AB%D8%A7%D9%84%D8%A7-%D9%84%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-yum-r282/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_11/yum.png.4642a66c59bdea900ceb4aac13a9adc5.png" /></p>

<p>
	يتناول هذا المقال كيفية تثبيت الحزم، تحديثها، حذفها، البحث عنها وإدارة مستودعاتها Repositories على توزيعة لينكس تستخدم مدير الحزم YUM الذي تُطوّره شركة Red Hat. يُمكن استخدام الأمثلة المذكورة في هذا الدّرس، والتي جُرِّبت على خادوم Red Hat Enterprise Linux 7، لأغراض الدراسة، التحضير ل<a href="https://academy.hsoub.com/certificates/redhat/" rel="">شهادة متخصّصة</a> أو لاستكشاف طرق جديدة لتثبيت الحزم والإبقاء على نظامك محدَّثا.<br>
	يجب، لكي تتبع الأمثلة المقدَّمة في هذا الدرس، أن يكون لديك فهم لأساسيات عمل الأوامر في لينكس وتوزيعة تستخدم YUM للتجربة عليها، Fedora أو <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-red-hat-enterprise-linux-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-virtualbox-r249/" rel="">Red Hat Enterprise Linux 7</a> على سبيل المثال.
</p>

<h2 id="ما-هو-مدير-الحزم-yum">
	ما هو مدير الحزم YUM؟
</h2>

<p>
	يُستخدَم مدير الحزم YUM (اختصار لـYellowdog Updater Modified) لإدارة البرامج المُحزَّمة بصيغة RPM (RedHat Package Manager). يمكن استخدام YUM من سطر الأوامر أو عبر واجهة رسومية. يتيح مدير الحزم YUM لمدير النظام تثبيت الحزم، تحديثها، حذفها أو البحث عنها. يُوزَّع مدير الحزم YUM حسب رخصة غنو GNU العمومية.
</p>

<ol>
<li>
		<p>
			تثبيت الحزم
		</p>

		<p>
			يُستخدَم الأمر <code>install</code> في مدير الحزم YUM على النحو التالي لتثبيت حزمة برنامج يُسمَّى Firefox. يتولّى مدير الحزم تثبيت الاعتمادات Dependencies، أي البرامج والمكتبات Libraries التي يتطلب عملُ الحزمة Firefox وجودَها (يجب أن تكون لديك صلاحيات المستخدم الجذر لتثبيت الحزم):
		</p>

		<pre class="ipsCode" id="ips_uid_1159_7">
[root@academy1 ~]# yum install firefox
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Resolving Dependencies
--&gt; Running transaction check
---&gt; Package firefox.x86_64 0:45.3.0-1.el7_2 will be installed
--&gt; Finished Dependency Resolution

Dependencies Resolved

=========================================================================
Package       Arch      Version            Repository                Size
=========================================================================
Installing:
firefox       x86_64    45.3.0-1.el7_2     rhel-7-server-eus-rpms    76 M

Transaction Summary
=========================================================================
Install  1 Package

Total download size: 76 M
Installed size: 142 M
Is this ok [y/d/N]: y
Downloading packages:
(...)
Installed:
firefox.x86_64 0:45.3.0-1.el7_2                                                                                                                     

Complete!</pre>

		<p>
			يطلُب الأمر أعلاه التأكيد (<code>Is this ok</code>) قبل البدء في تنزيل الحزمة وتثبيتها (اكتب <code>y</code> ثم اضغط على زرّ<code>Enter</code> للتأكيد). استخدم الخيار <code>y-</code> إن كنت ترغب في تثبيت الحزم تلقائيا دون طلب التأكيد:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_1159_9">
# yum -y install firefox
</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			حذف حزمة
		</p>

		<p>
			يحذف الأمر التالي الحزمة firefox تماما من النظام (بما في ذلك اعتماداتها):
		</p>

		<pre class="ipsCode" id="ips_uid_3372_7">
[root@academy1 ~]# yum remove firefox
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Resolving Dependencies
--&gt; Running transaction check
---&gt; Package firefox.x86_64 0:45.3.0-1.el7_2 will be erased
--&gt; Finished Dependency Resolution

Dependencies Resolved

===========================================================================================
Package          Arch              Version           Repository                    Size
===========================================================================================
Removing:
firefox          x86_64           45.3.0-1.el7_2     @rhel-7-server-eus-rpms       142 M

Transaction Summary
===========================================================================================
Remove  1 Package

Installed size: 142 M
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Erasing    : firefox-45.3.0-1.el7_2.x86_64                                                                                                      1/1 
Verifying  : firefox-45.3.0-1.el7_2.x86_64                                                                                                      1/1 

Removed:
firefox.x86_64 0:45.3.0-1.el7_2                                                                                                                     

Complete!</pre>

		<p>
			يطلُب الأمر التأكيد قبل حذف الحزمة. استخدم الخيار <code>y-</code> لتعطيل طلب التأكّد كالتالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_9">
# yum -y remove firefox</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تحديث حزمة
		</p>

		<p>
			فلنفترض أن لديك حزمة MySQL قديمة، لم تُحدَّث منذ زمن؛ وترغب في تحديثها إلى آخر إصدار. الأمر التالي يؤدي المهمة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_11">
# yum update mysql</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد قائمة بالحزم
		</p>

		<p>
			يُستخدَم أمر السرد <code>list</code> للبحث عن حزمة معيّنة عن طريق اسمها. يبحث الأمر التالي عن حزمة باسم <code>openssh</code>:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_3372_13">
[root@academy1 ~]# yum list openssh
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Installed Packages
openssh.x86_64                  6.6.1p1-25.el7_2                  @rhel-7-server-eus-rpms
</pre>

		<p>
			يمكن جعل البحث أكثر دقة بذكر إصدار الحزمة إن عُرِف؛ مثلا:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_15">
# yum list openssh-6.6.1p1</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			البحث عن حزمة
		</p>

		<p>
			يمكن استخدام الأمر <code>search</code> للبحث عن حزمة لا تتذكر اسمها بالضبط؛ مثلا نبحث عن <code>ftp</code>:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_17">
[root@academy1 ~]# yum search ftp
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
================== N/S matched: ftp =================================
ftp.x86_64 : The standard UNIX FTP (File Transfer Protocol) client
tftp.x86_64 : The client for the Trivial File Transfer Protocol (TFTP)
tftp-server.x86_64 : The server for the Trivial File Transfer Protocol (TFTP)
vsftpd.x86_64 : Very Secure Ftp Daemon
curl.x86_64 : A utility for getting files from remote servers (FTP, HTTP, and others)
lftp.i686 : A sophisticated file transfer program
lftp.x86_64 : A sophisticated file transfer program
wget.x86_64 : A utility for retrieving files using the HTTP or FTP protocols

Name and summary matches only, use "search all" for everything.</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			الحصول على معلومات عن حزمة
		</p>

		<p>
			استخدم الأمر <code>info</code> للحصول على معلومات عن حزمة؛ مثلا قبل تثبيتها:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_19">
[root@academy1 ~]# yum info firefox
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Available Packages
Name        : firefox
Arch        : x86_64
Version     : 45.3.0
Release     : 1.el7_2
Size        : 76 M
Repo        : rhel-7-server-eus-rpms/7Server/x86_64
Summary     : Mozilla Firefox Web browser
URL         : http://www.mozilla.org/projects/firefox/
License     : MPLv1.1 or GPLv2+ or LGPLv2+
Description : Mozilla Firefox is an open-source web browser, designed for standards
            : compliance, performance and portability.</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد جميع الحزم المتوفّرة
		</p>

		<p>
			يسرُد الأمر <code>list</code> عند استخدامها دون معطيات جميع الحزم المتوفرة في المستودعات؛ وهي كثيرة؛ لذا <a href="https://academy.hsoub.com/devops/linux/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D8%A5%D8%B9%D8%A7%D8%AF%D8%A9-%D8%AA%D9%88%D8%AC%D9%8A%D9%87-%D8%A7%D9%84%D8%A5%D8%AF%D8%AE%D8%A7%D9%84%D8%A7%D9%84%D8%A5%D8%AE%D8%B1%D8%A7%D8%AC-io-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r39/" rel="">أعد توجيه</a> نتيجة أمر السّرد إلى <a href="https://academy.hsoub.com/devops/linux/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D9%91%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AA%D9%86%D9%82%D9%91%D9%84-%D9%81%D9%8A-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r24/" rel="">الأمر <code>less</code></a> لتيسير عمليّة التصفح:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_21">
[root@academy1 ~]# yum list | less</pre>

		<p>
			استخدم المعطى <code>installed</code> إن أردت أن يقتصر السّرد على الحزم المثبّتة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_23">
[root@academy1 ~]# yum list installed | less</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			العثور على حزمة انطلاقا من ملفّ
		</p>

		<p>
			يُستخدَم الأمر <code>provides</code> في مدير الحزم YUM لمعرفة الحزمة التي يتبع لها ملفّ مّا. مثلا؛ نريد معرفة الحزمة التي توفّر ملفّ الإعداد <code>etc/httpd/conf/httpd.conf/</code>، لذا ننفذ الأمر بالطريقة التالية:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_25">
[root@academy1 ~]# yum provides /etc/httpd/conf/httpd.conf
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
httpd-2.4.6-17.el7.x86_64 : Apache HTTP Server
Repo        : rhel-7-server-eus-rpms
Matched from:
Filename    : /etc/httpd/conf/httpd.conf

httpd-2.4.6-17.el7.x86_64 : Apache HTTP Server
Repo        : rhel-7-server-rpms
Matched from:
Filename    : /etc/httpd/conf/httpd.conf</pre>

		<p>
			يُظهر الأمر اسم الحزمة والمستودع الذي تأتي منه.
		</p>
	</li>
	<li>
		<p>
			التحقق من وجود تحديثات وتحديث النظام
		</p>

		<p>
			استخدم الأمر <code>yum check-update</code> لمعرفة الحزم المثبّتة التي تتوفّر لها تحديثات. أما إن أردت تحديث الحزم إلى آخر إصدار متوفّر فالأمر <code>yum update</code> يؤدي المهمة.
		</p>
	</li>
	<li>
		<p>
			سرد مجموعات الحزم
		</p>

		<p>
			تُجمَّع كثير من الحزم في مجموعات لتسهيل التعامل معها؛ فبدلا من تثبيت هذه الحزم الواحدة تلو الآخرى، أو كتابة أسمائها جميعا، يمكن تثبيتها دفعة واحدة عن طريق اسم المجموعة. استخدم الأمر <code>grouplist</code> لسرد مجموعات الحزم المتوفّرة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_27">
[root@academy1 ~]# yum grouplist
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Available Environment Groups:
Minimal Install
Infrastructure Server
File and Print Server
Basic Web Server
Virtualization Host
Server with GUI
Installed Groups:
Development Tools
Graphical Administration Tools
Legacy UNIX Compatibility
Security Tools
System Administration Tools
Available Groups:
Compatibility Libraries
Console Internet Tools
RT
Scientific Support
Smart Card Support
System Management
Done</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تثبيت مجموعة حزم
		</p>

		<p>
			استخدم الأمر <code>groupinstall</code> لتثبيت مجموعة حزم. يثبّت الأمر التالي مجموعة حزم File and Print Server (خادوم الطباعة وتشارك الملفات):
		</p>

		<pre class="ipsCode" id="ips_uid_3372_29">
[root@academy1 ~]# yum groupinstall 'File and Print Server'
Dependencies Resolved

======================================================================================
Package             Arch        Version               Repository                  Size
======================================================================================
Installing for group install "File and Storage Server":
cifs-utils          x86_64      6.2-7.el7             rhel-7-server-eus-rpms      84 k
nfs4-acl-tools      x86_64      0.3.3-14.el7          rhel-7-server-eus-rpms      47 k
targetcli           noarch      2.1.fb41-3.el7        rhel-7-server-eus-rpms      61 k
targetd             noarch      0.7.1-1.el7           rhel-7-server-eus-rpms      48 k
Installing for dependencies:
PyYAML              x86_64      3.10-11.el7           rhel-7-server-eus-rpms      153 k
libyaml             x86_64      0.1.4-11.el7_0        rhel-7-server-eus-rpms      55 k
lvm2-python-libs    x86_64      7:2.02.130-5.el7_2.5  rhel-7-server-eus-rpms      166 k
pyparsing           noarch      1.5.6-9.el7           rhel-7-server-eus-rpms      94 k
python-configshell  noarch      1:1.1.fb18-1.el7      rhel-7-server-eus-rpms      67 k
python-kmod         x86_64      0.9-4.el7             rhel-7-server-eus-rpms      57 k
python-rtslib       noarch      2.1.fb57-3.el7        rhel-7-server-eus-rpms      88 k
python-setproctitle x86_64      1.1.6-5.el7           rhel-7-server-eus-rpms      15 k
python-urwid        x86_64      1.1.1-3.el7           rhel-7-server-eus-rpms      654 k

Transaction Summary
=========================================================================================
Install  4 Packages (+9 Dependent packages)

Total download size: 1.6 M
Installed size: 5.7 M
Is this ok [y/d/N]:</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تحديث مجموعة حزم
		</p>

		<p>
			يُستخدَم الأمر <code>groupupdate</code> على النحو التالي لتحديث مجموعة حزم سبق تثبيتها:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_31">
[root@academy1 ~]# yum groupupdate 'File and Print Server'</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			حذف مجموعة حزم
		</p>

		<p>
			استخدم الأمر <code>groupremove</code> لحذف مجموعة حزم مثبتة؛ مثلا لحذف مجموعة الحزم السابقة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_33">
[root@academy1 ~]#  yum groupremove 'File and Print Server'</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			سرد مستودعات YUM
		</p>

		<p>
			يمكن سرد المستودعات المفعَّلة في مدير الحزم YUM باستخدام الأمر التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_37">
[root@academy1 ~]# yum repolist 
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
repo id                                            repo name                                                                                    status
!rhel-7-server-eus-rpms/7Server/x86_64             Red Hat Enterprise Linux 7 Server - Extended Update Support (RPMs)                           11,241
!rhel-7-server-rpms/7Server/x86_64                 Red Hat Enterprise Linux 7 Server (RPMs)                                                     11,250
!rhel-7-server-rt-beta-rpms/x86_64                 Red Hat Enterprise Linux for Real Time Beta (RHEL 7 Server) (RPMs)                               15
!rhel-7-server-rt-rpms/7Server/x86_64              Red Hat Enterprise Linux for Real Time (RHEL 7 Server) (RPMs)                                   129
!rhel-ha-for-rhel-7-server-eus-rpms/7Server/x86_64 Red Hat Enterprise Linux High Availability (for RHEL 7 Server) - Extended Update Support (RP    224
!rhel-ha-for-rhel-7-server-rpms/7Server/x86_64     Red Hat Enterprise Linux High Availability (for RHEL 7 Server) (RPMs)                           224
!rhel-rs-for-rhel-7-server-eus-rpms/7Server/x86_64 Red Hat Enterprise Linux Resilient Storage (for RHEL 7 Server) - Extended Update Support (RP    279
!rhel-rs-for-rhel-7-server-rpms/7Server/x86_64     Red Hat Enterprise Linux Resilient Storage (for RHEL 7 Server) (RPMs)                           279
repolist: 23,641</pre>

		<p>
			أضف الخيار <code>all</code> إلى الأمر السابق إن أردت سرد جميع المستودعات بما فيها تلك غير المفعَّلة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_39">
[root@academy1 ~]# yum repolist  all</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تثبيت حزمة مع تحديد المستودع
		</p>

		<p>
			يُستخدم الخيار <code>enablerepo--</code> في أمر التثبيت لتحديد المستودع الذي نريد تنزيل الحزمة منه:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_41">
[root@academy1 ~]# yum --enablerepo=rhel-7-server-rpms install postgresql
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Resolving Dependencies
--&gt; Running transaction check
---&gt; Package postgresql.x86_64 0:9.2.15-1.el7_2 will be installed
--&gt; Processing Dependency: postgresql-libs(x86-64) = 9.2.15-1.el7_2 for package: postgresql-9.2.15-1.el7_2.x86_64
--&gt; Processing Dependency: libpq.so.5()(64bit) for package: postgresql-9.2.15-1.el7_2.x86_64
--&gt; Running transaction check
---&gt; Package postgresql-libs.x86_64 0:9.2.15-1.el7_2 will be installed
--&gt; Finished Dependency Resolution

Dependencies Resolved

=======================================================================================
Package           Arch          Version             Repository                    Size
=======================================================================================
Installing:
postgresql        x86_64        9.2.15-1.el7_2      rhel-7-server-eus-rpms        3.0 M
Installing for dependencies:
postgresql-libs   x86_64        9.2.15-1.el7_2      rhel-7-server-eus-rpms        231 k

Transaction Summary
========================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 3.2 M
Installed size: 16 M
Is this ok [y/d/N]:</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			صدفة YUM تفاعلية
		</p>

		<p>
			يتيح مدير الحزم YUM صدفة Shell لتنفيذ أوامر عدّة لإدارة الحزم:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_43">
[root@academy1 ~]# yum shell
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
&gt; update
&gt; repolist
repo id                                           repo name                                                                                     status
rhel-7-server-eus-rpms/7Server/x86_64             Red Hat Enterprise Linux 7 Server - Extended Update Support (RPMs)                            11,241
rhel-7-server-rpms/7Server/x86_64                 Red Hat Enterprise Linux 7 Server (RPMs)                                                      11,250
rhel-7-server-rt-beta-rpms/x86_64                 Red Hat Enterprise Linux for Real Time Beta (RHEL 7 Server) (RPMs)                                15
rhel-7-server-rt-rpms/7Server/x86_64              Red Hat Enterprise Linux for Real Time (RHEL 7 Server) (RPMs)                                    129
rhel-ha-for-rhel-7-server-eus-rpms/7Server/x86_64 Red Hat Enterprise Linux High Availability (for RHEL 7 Server) - Extended Update Support (RPM    224
rhel-ha-for-rhel-7-server-rpms/7Server/x86_64     Red Hat Enterprise Linux High Availability (for RHEL 7 Server) (RPMs)                            224
rhel-rs-for-rhel-7-server-eus-rpms/7Server/x86_64 Red Hat Enterprise Linux Resilient Storage (for RHEL 7 Server) - Extended Update Support (RPM    279
rhel-rs-for-rhel-7-server-rpms/7Server/x86_64     Red Hat Enterprise Linux Resilient Storage (for RHEL 7 Server) (RPMs)                            279
&gt; exit
Leaving Shell</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			عرض سجلّ أوامر YUM
		</p>

		<p>
			يُستخدَم الأمر <code>history</code> على النحو التالي لعرض قائمة بآخر أوامر YUM المنفّذة:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_45">
[root@academy1 ~]# yum history 
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
ID      | Login user               | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    14 | Mohamed ... &lt;meyil&gt;      | 2016-09-01 23:57 | Erase        |    1   
    13 | Mohamed ... &lt;meyil&gt;      | 2016-09-01 23:48 | Install        |    1   
    12 | Mohamed ... &lt;meyil&gt;      | 2016-08-02 23:41 | I, U            |    6   
    11 | Mohamed ... &lt;meyil&gt;      | 2016-07-31 23:19 | Install         |    2   
    10 | Mohamed ... &lt;meyil&gt;      | 2016-07-21 22:09 | Install         |    1   
    9   | Mohamed ... &lt;meyil&gt;      | 2016-07-21 15:29 | Install        |    4   
    8   | Mohamed ... &lt;meyil&gt;      | 2016-07-21 14:18 | I, U           |   75   
    7   | Mohamed ... &lt;meyil&gt;      | 2016-06-11 01:32 | Erase          |    1   
    6   | Mohamed ... &lt;meyil&gt;      | 2016-06-07 13:51 | Update         |    1   
    5   | Mohamed ... &lt;meyil&gt;      | 2016-06-05 02:57 | Install        |    2   
    4   | Mohamed ... &lt;meyil&gt;      | 2016-06-05 02:56 | Update         |    1   
    3   | Mohamed ... &lt;meyil&gt;      | 2016-05-28 03:16 | Install        |    1   
    2   | Mohamed ... &lt;meyil&gt;      | 2016-05-28 02:45 | I, U           |  190 EE
    1   | System &lt;unset&gt;             | 2016-05-27 20:43 | Install        | 1293   
history list</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تنظيف تخبئة Cache مدير الحزم
		</p>

		<p>
			يحتفظ مدير الحزم YUM بنسخ من البيانات المتعلقة بالحزم ضمن مجلّد <code>var/cache/yum/</code>؛ يمكن حذف جميع هذه النسخ بتنفيذ الأمر التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_3372_47">
[root@academy1 ~]# yum clean all
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
Cleaning repos: rhel-7-server-eus-rpms rhel-7-server-rpms rhel-7-server-rt-beta-rpms rhel-7-server-rt-rpms rhel-ha-for-rhel-7-server-eus-rpms
            : rhel-ha-for-rhel-7-server-rpms rhel-rs-for-rhel-7-server-eus-rpms rhel-rs-for-rhel-7-server-rpms
Cleaning up everything</pre>

		<p>
			 
		</p>
	</li>
</ol>
<p>
	ترجمة - بتصرّف - لمقال<a href="http://www.tecmint.com/20-linux-yum-yellowdog-updater-modified-commands-for-package-mangement/" rel="external nofollow">20 Linux YUM (Yellowdog Updater, Modified) Commands for Package Management</a> لصاحبه Ravi Saive.
</p>
]]></description><guid isPermaLink="false">282</guid><pubDate>Wed, 26 Oct 2016 11:18:00 +0000</pubDate></item><item><title>10 &#x623;&#x645;&#x62B;&#x644;&#x629; &#x644;&#x62C;&#x62F;&#x648;&#x644;&#x629; &#x627;&#x644;&#x645;&#x647;&#x627;&#x645; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Cron</title><link>https://academy.hsoub.com/devops/linux/10-%D8%A3%D9%85%D8%AB%D9%84%D8%A9-%D9%84%D8%AC%D8%AF%D9%88%D9%84%D8%A9-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D9%85-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-cron-r281/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_11/cron.png.47a679f065c2b012e32d646760a45f4d.png" /></p>

<p>
	يتكرّر أحيانا تنفيذ مهامّ وعمليات بحيث يستهلك إتمامها يدويا الكثير من الوقت. يمكن في هذه الحالة اللجوء إلى جدولة المهام لتنفيذها دوريّا في الخلفية، دون الحاجة للتدخل اليدوي، حسب معايير زمنية محدّدة مسبقا. سنرى في هذا المقال كيف يمكننا استخدام أداة <a href="https://academy.hsoub.com/tags/cron/" rel="">Cron</a> والأوامر المصاحبة لها من أجل تنفيذ إجراءات دوريا في الخلفية. يكثُر استخدام Cron لتنفيذ مهامّ النسخ الاحتياطي Backup، تحديث الحزم ومزامنة Synchronization الملفات؛ على سبيل المثال.
</p>

<p>
	يقوم مبدأ عمل Cron على التحقق كلّ دقيقة من العناصر الموجودة في الجدول الخاصّ به (ملفّ)، ويُسمّى Crontab (اختصار لـCron table؛ جدول Cron). تحدّد عناصر Crontab المهامّ المُجدوَلة والمجالات الزمنية لتنفيذها.
</p>

<p>
	<strong>ملحوظة:</strong> يُفعَّل Cron مبدئيا لجميع المستخدمين، فيحصُل كل مستخدم على جدول Cron خاصّ به؛ إلا أنه يمكن، عبر الملفّ <code>etc/cron.deny/</code>، تغيير هذا الإعداد وتقييد إمكانيّة جدولة المهامّ بالنسبة للمستخدمين.
</p>

<p>
	توجد في ملفّ Crontab أسطر تتكوّن من ستة حقول يُفصل بينها بمسافة أو علامة جدولة (زرّ Tab في لوحة المفاتيح). تُمثّل الحقول الخمسة الأولى من الملفّ المجال الزمني لتنفيذ الأمر الموجود في الحقل السادس؛ وهي على النحو التالي (ابتداءً من اليسار):
</p>

<ul>
<li>
		الدقيقة: يأخذ هذا الحقل قيما عددية في المجال من 0 إلى 59.
	</li>
	<li>
		الساعة: يأخذ قيما تتراوح بين 0 و23.
	</li>
	<li>
		اليوم (في الشهر): يأخذ قيمة من 1 إلى 31.
	</li>
	<li>
		الشهر: يأخذ قيمة عددية في المجال من 1 إلى 12؛ كما يمكن تحديد الأحرف الأولى من اسم الشهر (Jan وDec ليناير ودجمبر على التوالي).
	</li>
	<li>
		اليوم (في الأسبوع): يأخذ قيمة في المجال من 0 إلى 6. يمثّل العدد <code>0</code> يوم الأحد، <code>1</code> الاثنين.. و<code>6</code> السبت. كما يمكن تعيين الأحرف الثلاثة الأولى من اليوم (Wed مثلا بالنسبة ليوم الأربعاء).
	</li>
</ul>
<p>
	بالنسبة للحقل السادس فهو - كما أسلفنا - الأمر الذي نريد تنفيذه في الوقت المحدّد عن طريق الحقول الزمنية السابقة.
</p>

<ol>
<li>
		<p>
			سرد المهامّ الموجودة في جدول Cron
		</p>

		<p>
			يُستخدَم الخيار <code>l-</code> مع الأمر <code>crontab</code> لسرد قائمة بأسطر (مهامّ) المستخدم الحالي المضبوطة في جدول Crontab:
		</p>

		<pre class="ipsCode" id="ips_uid_8877_8">
$ crontab -l
00 10 * * * /bin/ls &gt;/ls.txt</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			التعديل على المهام المُجدولة
		</p>

		<p>
			يتيح الخيّار <code>e-</code> مع الأمر <code>crontab</code> التعديل على المهامّ المجدولة بتغيير إعداداتها في الملف Crontab:
		</p>

		<pre>
 </pre>

		<pre class="ipsCode" id="ips_uid_8877_10">
$ crontab -e
</pre>

		<p>
			يفتح الأمر جدول المهامّ بمحرّر النصوص المبدئي (أو يُظهر قائمة بالمحرّرات المتاحة للاختيار منها). يمكن بعدها تغيير الإعدادات ثم حفظ الملف.
		</p>
	</li>
	<li>
		<p>
			سرد المهام المجدولة لمستخدم
		</p>

		<p>
			يُحدّد الخيار <code>u-</code> المستخدم الذي نريد سرد مهامّه؛ وذلك على النحو التالي:
		</p>

		<pre class="ipsCode" id="ips_uid_8877_12">
$ crontab -u academy -l
no crontab for academy</pre>

		<p>
			يطلُب الأمر أعلاه سرد المهام المجدولة الخاصّة بالمستخدم <code>academy</code>، وتشير النتيجة إلى عدم وجود مهام مجدولة لهذا المستخدم.
		</p>

		<p>
			<strong>ملحوظة:</strong> لا يمكن لمستخدم عادي سرد مهام مستخدم آخر؛ لا تُتاح هذه الصلاحية سوى للمستخدم الجذر.
		</p>
	</li>
	<li>
		<p>
			حذف المهام المجدولة
		</p>

		<p>
			ينبغي الحذر عند استخدام الخيار <code>r-</code> مع الأمر <code>crontab</code> إذ أنه يحذف جميع المهام المجدولة، دون طلب تأكيد الأمر. أضف الخيار <code>i-</code>، الذي يطلُب تأكيد الحذف، بدلا من استخدام <code>r-</code> لوحده:
		</p>

		<pre class="ipsCode" id="ips_uid_8877_14">
$ crontab -i -r
crontab: really delete academy's crontab?</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			تخصيص المدة الزمنية باستخدام المحارف الخاصّة (<code>*</code>، <code>-</code>، <code>/</code> و<code>#</code>)
		</p>

		<p>
			تُستخدَم هذه المحارف لتخصيص الحقول الزمنية في أسطر جدول المهام:
		</p>

		<ul>
<li>
				يعني استخدام العلامة <code>*</code> في أحد الحقول الخمسة الأولى من السّطر أننا نريد تنفيذ الأمر مهما كانت قيمة هذا الحقل. مثلا؛ إن استُخدمت في الحقل الثاني فهذا يعني أن المطلوب تنفيذ الأمر بغض النظر عن الساعة.
			</li>
			<li>
				تُستخدَم العلامة <code>-</code> لتعريف مجال بالنسبة للحقل. مثلا <code>9-0</code> في حقل الدقيقة تعني أن المطلوب تنفيذ الأمر في الدقائق من <code>0</code> إلى <code>9</code>.
			</li>
			<li>
				يُساعد الخط المائل <code>/</code> في تقسيم الحقل. مثلا <code>10/</code> في حقل الدقائق تعني كل عشر دقائق.
			</li>
			<li>
				تفرّق الفاصلة <code>,</code> بين عناصر عدّة في نفس الحقل. مثلا؛ <code>1,3,5</code> في الحقل الخامس تعني أننا نريد تنفيذ المهمة أيام الاثنين، الأربعاء والخميس.
			</li>
		</ul>
</li>
	<li>
		<p>
			جدولة المهام على مستوى النظام
		</p>

		<p>
			يُمكن لمديري الأنظمة استخدام مجلدات معدّة مسبقا لتنفيذ مهام على مستوى النظام. تُنفَّذ <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r252/" rel="">السكربتات</a> الموجودة في المجلدات التاليّة -على الترتيب - مرة كلّ يوم، مرة كلّ ساعة، مرة في الشّهر ومرة في الأسبوع:
		</p>

		<pre class="ipsCode" id="ips_uid_8877_19">
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly</pre>

		<p>
			كما يُمكن استخدام المجلّد <code>etc/cron.d/</code> لجدولة المهام بوضع ملفات تشبه في صيغتها Crontab؛ مع زيادة حقل، بعد الحقول الزمنية وقبل الأمر (ليصبح العدد الإجمالي للحقول سبعة)، للمستخدم الذي تُنفَّذ باسمه المهمة.
		</p>
	</li>
	<li>
		<p>
			تنفيذ أمر عند وقت معيَّن
		</p>

		<p>
			نستخدم في المثال أدناه الأمر <code>crontab -e</code> للتعديل على جدول المهام ثم نضيف سطرا جديدا لمهمة تحذف جميع الملفات الفارغة في المجلّد <code>tmp/</code>. تُنفَّذ المهمة يوميا عند الساعة 00 (منتصف الليل) و30 دقيقة.
		</p>

		<pre class="ipsCode" id="ips_uid_8877_25">
# crontab -e
30 0 * * *   find /tmp -type f -empty -delete</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			المدد الزمنية الشائعة
		</p>

		<p>
			يمكنك استخدام سلاسل المحارف التالية مكانَ الحقول الزمنية الخمسة
		</p>

		<table><tbody>
<tr>
<th>
						سلسلة المحارف   
					</th>
					<th>
						العمل
					</th>
				</tr>
<tr>
<td>
						<code>reboot@</code>
					</td>
					<td>
						تنفيذ الأمر عندما يعاد تشغيل النظام
					</td>
				</tr>
<tr>
<td>
						<code>daily@</code>
					</td>
					<td>
						مرة في اليوم. يمكن أيضا استخدام <code>@midnight</code> للتنفيذ عند منتصف الليل.
					</td>
				</tr>
<tr>
<td>
						<code>weekly@</code>
					</td>
					<td>
						مرة في الأسبوع.
					</td>
				</tr>
<tr>
<td>
						<code>yearly@</code>
					</td>
					<td>
						مرة في السنة.
					</td>
				</tr>
</tbody></table>
</li>
	<li>
		<p>
			تنفيذ أوامر عدّة
		</p>

		<p>
			تُستخدم العلامة <code>&amp;&amp;</code> في حقل الأمر لتحديد أكثر من أمر للتنفيذ؛ مثلا:
		</p>

		<pre class="ipsCode" id="ips_uid_8877_23">
@daily command1 &amp;&amp; command2</pre>

		<p>
			يطلب السّطر السابق تنفيذ الأمر <code>command1</code> و<code>command2</code> يوميا.
		</p>
	</li>
	<li>
		<p>
			تعطيل إشعارات البريد
		</p>

		<p>
			يُرسل Cron مبدئيا رسائل بريد إلى المستخدم عند تنفيذ المهام المجدولة (في حال كان النظام الذي يعمل عليه قادرا على ذلك). يمكن تعطيل هذه الإشعارات بإضافة السطر التالي إلى Crontab (عن طريق الأمر <code>crontab -e</code>):
		</p>

		<pre class="ipsCode" id="ips_uid_8877_27">
* * * * * &gt;/dev/null 2&gt;&amp;1</pre>

		<p>
			 
		</p>
	</li>
</ol>
<p>
	ترجمة - بتصرّف - لمقال <a href="http://www.tecmint.com/11-cron-scheduling-task-examples-in-linux/" rel="external nofollow">11 Cron Scheduling Task Examples in Linux</a> لصاحبه Ravi Saive.
</p>
]]></description><guid isPermaLink="false">281</guid><pubDate>Mon, 17 Oct 2016 00:07:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x646;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x627;&#x644;&#x645;&#x647;&#x627;&#x645; &#x627;&#x644;&#x645;&#x62C;&#x62F;&#x648;&#x644;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Cron &#x641;&#x64A; &#x623;&#x646;&#x638;&#x645;&#x629; &#x644;&#x64A;&#x646;&#x643;&#x633; &#x648;&#x64A;&#x648;&#x646;&#x643;&#x633;</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D9%86%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AC%D8%AF%D9%88%D9%84%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-cron-%D9%81%D9%8A-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D9%84%D9%8A%D9%86%D9%83%D8%B3-%D9%88%D9%8A%D9%88%D9%86%D9%83%D8%B3-r277/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_07/linux-unix-cron.png.6c3fef22a1014736760882ca21cf21fc.png" /></p>

<p>
	تستخدم المهام المجدولة باستخدام الأداة Cron لجدولة تنفيذ الأوامر في وقت محدد، حيث يمكن إعداد الأوامر أو السكربتات، التي يمكن أن يتم تنفيذها بشكل متكرر في وقت مجدد. يُعتبر Cron أحد أكثر الأدوات إفادة في أنظمة لينكس وشبيهات يونكس، حيث تعمل خدمة <span style="font-family:courier new,courier,monospace;">cron</span> في الخلفية وتتحقق باستمرار من ملف <span style="font-family:courier new,courier,monospace;">etc/crontab/</span>، ومجلّدات<span style="font-family:courier new,courier,monospace;"> /.*etc/cron/</span>، كما تتحقق من مجلد <span style="font-family:courier new,courier,monospace;">/var/spool/cron/</span>.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="18272" data-unique="k67ztrmt5" src="https://academy.hsoub.com/uploads/monthly_2016_07/linux-unix-cron.png.22224c1188006964e8eb95b6698e2005.png" alt="linux-unix-cron.png"></p>

<h2>
	أمر crontab
</h2>

<p>
	يستخدم أمر <span style="font-family:courier new,courier,monospace;">crontab</span> لتثبيت، إلغاء تثبيت أو عرض الجداول (ملف إعدادات <span style="font-family:courier new,courier,monospace;">cron</span>) المستخدم في قيادة خدمة <span style="font-family:courier new,courier,monospace;">cron</span> في برمجية Vixie Cron.
</p>

<p>
	يمكن لكل مستخدم أن يكون لديه ملف <span style="font-family:courier new,courier,monospace;">crontab</span> خاص به، وعلى الرغم من أنّها عبارة عن ملفّات في <span style="font-family:courier new,courier,monospace;">var/spool/cron/crontabs/</span> إلا أنها غير مخصصة ليتم التعديل عليها بشكل مباشر، حيث يجب استخدام الأمر <span style="font-family:courier new,courier,monospace;">crontab</span> لتعديل أو إعداد أي مهام مجدولة في <span style="font-family:courier new,courier,monospace;">cron</span>.
</p>

<h2>
	أنواع ملفات إعدادات cron
</h2>

<p>
	توجد أنواع مختلفة لملفات الإعدادات:
</p>

<h3>
	Crontab الخاصة بأنظمة لينكس/يونكس
</h3>

<p>
	عادةً ما تستخدم من قبل خدمات النظام والمهام المجدولة الحرجة التي تحتاج لصلاحيات مدير النظام root. ويستخدم الحقل السادس (انظر أدناه لمزيد من المعلومات عن الحقول) هو اسم المستخدم الذي سيتم تنفيذ الأمر وفق صلاحياته، وتعطي هذه المرونة إمكانية تنفيذ الأوامر وفق أي مستخدم.
</p>

<h3>
	Crontab الخاصة بالمستخدم
</h3>

<p>
	يمكن للمستخدم تثبيت مهامه المجدولة الخاصة باستخدام أمر <span style="font-family:courier new,courier,monospace;">crontab</span>، ويستخدم الحقل السادس لتحديد الأمر المُراد تنفيذه، ويتم تنفيذ جميع الأوامر وفق المستخدم الذي قام بإنشاء المُهمّة.
</p>

<p>
	<strong>ملاحظة</strong>: يعرض المقال تطبيقات cron المكتوبة من قبل Paul Vixie والمستخدمة في معظم توزيعات لينكس وشبيهات يونكس كالإصدار الرابع الشهير لنظام BSD. إن الصيغة متوافقة مع العديد من تطبيقات خدمة <span style="font-family:courier new,courier,monospace;">crond</span>.
</p>

<h2>
	ولكن كيف أقوم بتثبيت وإنشاء مهامي المجدولة الخاصة؟
</h2>

<p>
	للقيام بذلك، نقوم بتنفيذ الأمر التالي في سطر الأوامر على أنظمة لينكس وشبيهات يونكس:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_8">
<span class="pln">$ crontab -e</span></pre>

<p>
	إن صيغة الملف الذي سيظهر على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_10">
<span class="pln">1 2 3 4 5 /path/to/command arg1 arg2</span></pre>

<p>
	أو:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_12">
<span class="pln">1 2 3 4 5 /root/ntp_sync.sh</span></pre>

<p>
	حيث أن:
</p>

<ul>
<li>
		1: الدقيقة (0-59)
	</li>
	<li>
		2: الساعة (0-23)
	</li>
	<li>
		3: اليوم في الشهر (0-31)
	</li>
	<li>
		4: الشهر (0-12 حيث يمثل 12 شهر ديسمبر)
	</li>
	<li>
		5: اليوم في الأسبوع (0-7 حيث يمثل الرقم 0 أو 7 يوم الأحد)
	</li>
	<li>
		<span style="font-family:courier new,courier,monospace;">path/to/command/</span>: هو مسار السكربت أو اسم الأمر المراد جدولة تنفيذه.
	</li>
</ul>
<p>
	ويمكن تصوّر الصيغة على النحو الأسهل التالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			* * * * * الأمر المراد تنفيذه<br>
			– – – – –<br>
			| | | | |<br>
			| | | | —– ترتيب اليوم في الأسبوع (0 – 7) (الأحد=0 or 7)<br>
			| | | ——- الشهر (1 – 12)<br>
			| | ——— اليوم في الشهر (1 – 31)<br>
			| ———– الساعة (0 – 23)<br>
			————- الدقيقة (0 – 59)
		</p>
	</div>
</blockquote>

<p>
	مثال على crontab بسيط:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9188_7">
<span class="pln">## نفّذ سكربت backupscript كُل 5 دقائق ##
*/5 * * * * /root/backupscript.sh

## نفّذ سكربت backupscript يوميًا الساعة 1 صباحًا ##
0 1 * * * /root/backupscript.sh

## نفّذ سكربت backupscript شهريًا في اليوم الأول من الشهر في تمام الساعة 3:15 صباحًا ##
15 3 1 * * /root/backupscript.sh</span></pre>

<p>
	<strong>ملاحظة</strong>: يمكن إدراج تعليقات في ملف <span style="font-family:courier new,courier,monospace;">crontab</span> بوضع إشارة # في بداية السطر.
</p>

<h2>
	كيفية استخدام المعاملات operators
</h2>

<p>
	لابد أنك لاحظت في الأمر الأول من الأوامر السابقة أننا كتبنا */5 بدلًا من 5 فقط. إنّ إشارة / هي إحدى المعاملات وسنرى الآن كيفية استخدام المعاملات في crontab.
</p>

<p>
	تسمح المعاملات بتحديد عدة قيم في الحقل الواحد، وهناك 4 معاملات:
</p>

<ul>
<li>
		<strong>النجمة (*)</strong>: يحدد هذا المعامل جميع القيم الممكنة في الحقل الذي استخدمت فيه. فعلى سبيل المثال، استخدام <strong>*</strong> في حقل الساعة يعني أنه سيتم تنفيذ الأمر في "كل" ساعة خلال اليوم، واستخدامها في حقل الأشهر يعني أنه سيتم تنفيذ الأمر في "كل" شهر من أشهر السنة.
	</li>
	<li>
		<strong>الفاصلة (,)</strong>: يحدد هذا المعامل مجموعة من القيم، على سبيل المثال: "1,5,10,15,20,25"، فلو استخدمنا هذه السلسلة مثلًا في حقل الدقائق لعَنى ذلك أنه سيتم تنفيذ الأمر في الدقيقة الأولى، والخامسة، والعاشرة، والخامسة عشر، والعشرون، والخامسة والعشرون من الساعة.
	</li>
	<li>
		<strong>إشارة السالب (-)</strong>: يحدد هذا المعامل مجالًا من القيم، على سبيل المثال: "5-15"، فلو استخدمنا هذه القيمة في حقل الأيام مثلًا لعَنى ذلك أنه سيتم تنفيذ الأمر في اليوم الخامس، السادس، السابع، .... الرابع عشر، الخامس عشر من كل شهر; وكما نلاحظ فهذا يشبه تمامًا كتابة "5,6,7,8,9,10,11,12,13,14,15" باستخدام معامل الفاصلة (,).
	</li>
	<li>
		<strong>الخط المائل الخلفي (/)</strong>: يحدد هذا المعامل قيمة الخطوة، على سبيل المثال: "0-23/" يمكن استخدامها في حقل الساعة لتحديد أن الأمر سيتم تنفيذه في كُل ساعة، ويمكن استخدام هذا المعامل بعد معامل النجمة (*) فلو أردنا تنفيذ الأمر كل ساعتين فيمكن أن نكتب */2 في حقل الساعة.
	</li>
</ul>
<h2>
	استخدام الكلمات الخاصة لتوفير الوقت
</h2>

<p>
	عوضًا عن استخدام الحقول الخمسة الأولى من سطر crontab، يمكن استخدام إحدى الكلمات الخاصة الثمانية والتي لن توفّر الوقت فقط بل ستزيد من سهولة فهم المحتوى.
</p>

<ul>
<li>
		<strong><span style="font-family:courier new,courier,monospace;">reboot@</span></strong>: نفذ الأمر مرة واحدة عند كل إعادة تشغيل
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">early@</span></strong>: نفذ الأمر مرة واحدة في بداية كل سنة، يماثل كتابة "0 0 1 1 *"
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">annually@</span></strong>: مشابه لـ<span style="font-family:courier new,courier,monospace;"> yearly@</span> تمامًا
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">monthly@</span></strong>: نفذ الأمر مرة واحدة في بداية كل شهر، يماثل كتابة "0 0 1 * *"
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">weekly@</span></strong>: نفذ الأمر مرة واحدة في بداية كل أسبوع، يماثل كتابة "0 0 * * 0"
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">daily@</span></strong>: نفذ الأمر مرة واحدة في بداية كل يوم، يماثل كتابة "0 0 * * *"
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">midnight@</span></strong>: مشابه لـ <span style="font-family:courier new,courier,monospace;">daily@</span> تمامًا
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">hourly@</span></strong>: نفذ الأمر مرة واحدة في بداية كل ساعة، يماثل كتابة "0 * * * *"
	</li>
</ul>
<p>
	<strong>مثال</strong>:
</p>

<pre class="ipsCode" id="ips_uid_2658_7">
# نفذ أمر ntpdate كل ساعة
@hourly /path/to/ntpdate</pre>

<h2>
	المزيد من المعلومات عن ملف etc/crontab/ ومجلدات */etc/cron.d/
</h2>

<p>
	يُعدّ ملف <span style="font-family:courier new,courier,monospace;">etc/crontab/ </span>خاصًا بالنظام، وعادة ما يستخدم من قبل مدير النظام root أو الخدمات لإعداد مهام مجدولة على مستوى النظام ككل، ويجب على المستخدمين استخدام أمر <span style="font-family:courier new,courier,monospace;">crontab</span> لإعداد مهامهم المجدولة حسبما أوضحنا أعلاه.
</p>

<p>
	أمّا<span style="font-family:courier new,courier,monospace;"> /var/spool/cron/</span> أو <span style="font-family:courier new,courier,monospace;">/var/cron/tabs/</span> فهي مجلّدات لملفّات crontab الخاصة بالمستخدم، ويجب إنشاء نسخة احتياطية عنها مع مجلد home الخاص بكل مستخدم.
</p>

<h2>
	فهم ملف <span style="font-family:courier new,courier,monospace;">etc/crontab/</span> الافتراضي
</h2>

<p>
	يحتوي الملف بشكل افتراضي على ما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2658_9">
<span class="pln">SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts

01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly</span></pre>

<p>
	يتم في البداية تحديد بيئة الصدفة SHELL، وفيما لو لم يتم تحديد البيئة سيقوم <span style="font-family:courier new,courier,monospace;">cron</span> باستخدام الافتراضية sh.
</p>

<p>
	وفي حال لم يتم تحديد قيمة للمتغير <span style="font-family:courier new,courier,monospace;">PATH</span>، فلن يكون هناك قيمة افتراضية ويتوجب حينها تحديد مسار الأمر أو السكربت المطلوب تنفيذه بشكل مباشر absolute.
</p>

<p>
	أما في حال لم يتم تحديد قيمة للمتغير <span style="font-family:courier new,courier,monospace;">HOME</span>، فسيستخدم <span style="font-family:courier new,courier,monospace;">cron</span> مسار مجلد <span style="font-family:courier new,courier,monospace;">home</span> الخاص بالمستخدم الذي يقوم بالتنفيذ.
</p>

<p>
	بالإضافة إلى ما سبق، يقوم <span style="font-family:courier new,courier,monospace;">cron</span> بقراءة الملفات في مجلد <span style="font-family:courier new,courier,monospace;">/etc/cron.d/</span>، وعادة ما تقوم خدمات نظام مثل <span style="font-family:courier new,courier,monospace;">sa-update</span> أو <span style="font-family:courier new,courier,monospace;">sysstat</span> بوضع ملف مهامها المجدولة في هذا المجلّد.
</p>

<p>
	يمكن لمدير النظام root أو مستخدم بصلاحيات عالية superuser أن يستخدم هذه المجلّدات لإعداد المهام المجدولة، حيث بالإمكان إسقاط ملفات السكربتات في هذه المجلّدات مباشرة، ويقوم أمر <span style="font-family:courier new,courier,monospace;">run-parts</span> بتنفيذ السكربتات أو البرامج الموجودة في مجلّد يتم تحديده في ملف <span style="font-family:courier new,courier,monospace;">etc/crontab/</span>:
</p>

<ul>
<li>
		ضع جميع السكربتات هنا واستدعيها في ملف <span style="font-family:courier new,courier,monospace;">etc/crontab/</span>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_24">
<span class="pln">/etc/cron.d/</span></pre>

<ul>
<li>
		نفذ جميع السكربتات مرة في اليوم
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_22">
<span class="pln">/etc/cron.daily/</span></pre>

<ul>
<li>
		نفذ جميع السكربتات مرة في الساعة
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_20">
<span class="pln">/etc/cron.hourly/</span></pre>

<ul>
<li>
		نفذ جميع السكربتات مرة في الشهر
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_18">
<span class="pln">/etc/cron.monthly/</span></pre>

<ul>
<li>
		نفذ جميع السكربتات مرة في الأسبوع
	</li>
</ul>
<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_16">
<span class="pln">/etc/cron.weekly/</span></pre>

<h2>
	النسخ الاحتياطي للمهام المجدولة باستخدام cron
</h2>

<p>
	يمكن استخدام الأمرين التاليين لأخذ نسخة عن المهام المجدولة للمستخدم الذي يقوم بتنفيذ الأمرين، حيث سيتم حفظ قائمة بالمهام المجدولة في الملف المحدد في المسار:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7331_14">
<span class="pln"># crontab -l &gt; /path/to/file
# crontab -u user -l /path/to/file</span></pre>

<p>
	يسمح الأمر الثاني بتحديد اسم المستخدم الذي سيتم عرض المهام المجدولة الخاصة به، ويتوجب أن يملك المستخدم الذي يقوم بتنفيذ الأمر صلاحية لاستعراض المهام المجدولة الخاصة بالمستخدم المذكور، فمثلًا يملك مدير النظام صلاحية تمكّنه من استعراض المهام المجدولة الخاصة بأي مستخدم، ولكن لا يمكن لأي مستخدم استعراض المهام المجدولة الخاصة بمدير النظام ما لم يكن يملك صلاحية بذلك.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.unixmen.com/add-cron-jobs-linux-unix/" rel="external nofollow">HOW TO ADD CRON JOBS IN LINUX AND UNIX</a> لصاحبه Duy NguyenViet.
</p>
]]></description><guid isPermaLink="false">277</guid><pubDate>Fri, 01 Jul 2016 12:12:32 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x648;&#x627;&#x644;&#x625;&#x634;&#x627;&#x631;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639;&#x647;&#x627; &#x641;&#x64A; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts)</title><link>https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%88%D8%A7%D9%84%D8%A5%D8%B4%D8%A7%D8%B1%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r274/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-errors-signals.png.d03a4f19214582562278f2a60ebb3df0.png" /></p>

<p>
	سنلقي في هذا الدرس نظرةً إلى آلية التعامل مع الأخطاء و الإشارات أثناء تنفيذ السكربتات.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17886" data-unique="i5e6oe988" src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-errors-signals.png.e990b930ddf813c846ab4f53311b7f37.png" alt="shell-script-errors-signals.png"></p>

<p>
	يُقاس الفرق بين البرمجة الجيدة والتعيسة عادةً بمدة استقرار البرنامج ومرونته، أي قابلية تعامل البرنامج مع الحالات التي لا تسير فيها الأمور على ما يرام.
</p>

<h2>
	حالة الخروج
</h2>

<p>
	تتذكر من دروسنا السابقة أنَّ <a href="https://academy.hsoub.com/search/?tags=%D9%85%D8%AF%D8%AE%D9%84+%D8%A5%D9%84%D9%89+%D9%83%D8%AA%D8%A7%D8%A8%D8%A9+%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA+%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9" rel="">كل برنامج مكتوب بطريقة جيدة سيُعيد حالة خروج عندما ينتهي تنفيذه</a>؛ فإذا انتهى تنفيذ البرنامج بنجاح، فستكون حالة الخروج مساويةً للصفر، وإن كانت حالة الخروج مساوية لقيمة مختلفة عن الصفر، فهذا يدلّ أنَّ البرنامج قد واجهة مشكلةً ما منعته من إتمام مهمته.
</p>

<p>
	من المهم جدًا التحقق من حالة خروج البرامج التي تستدعيها في سكربتاتك، ومن المهم أيضًا أن تُعيد سكربتاتك حالة خروج مفيدة عندما تنتهي. لقد مرّ عليّ مدير أنظمة يونكس قد كتب سكربتًا لنظام إنتاجي يحتوي على السطرين الآتيين:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_13">
<span class="pln"># Example of a really bad idea

cd $some_directory
rm *</span></pre>

<p>
	هذه طريقة سيئة جدًا لكتابة البرامج، لأنها تعمل بشكلٍ جيد لو لم يحدث أيّ خطأ. فالسطر الأول ينقل مجلد العمل الحالي إلى المسار الموجود في المتغير ‎<span style="font-family:courier new,courier,monospace;">$some_directory</span> ثم يحذف جميع الملفات الموجودة في ذاك المجلد؛ وهذه هي الحالة الطبيعية لتنفيذ السكربت، لكن ماذا يحدث لو لم يكن المسار الموجود في المتغير ‎<span style="font-family:courier new,courier,monospace;">$some_directory</span> موجودًا؟ سيفشل -في هذه الحالة- تنفيذ الأمر <span style="font-family:courier new,courier,monospace;">cd</span> ثم سيُنفِّذ السكربتُ الأمرَ <span style="font-family:courier new,courier,monospace;">rm</span> في مجلد العمل الحالي، وهنا ستقع الكارثة!
</p>

<p>
	بالمناسبة، واجه سكربت مدير الأنظمة البائس هذه المشكلة ودمَّر جزءًا كبيرًا مهمًا من النظام الإنتاجي؛ لا تدع ذلك يحدث لك!
</p>

<p>
	مشكلة السكربت السابق أنَّه لم يتحقق من حالة خروج الأمر <span style="font-family:courier new,courier,monospace;">cd</span> قبل الاستمرار وتنفيذ الأمر <span style="font-family:courier new,courier,monospace;">rm</span>.
</p>

<h2>
	التحقق من حالة الخروج
</h2>

<p>
	هنالك عدِّة طرائق تستطيع فيها الحصول على حالة الخروج والتصرف وفقًا لها. أول طريقة هي معاينة محتويات متغير البيئة ‎$?‎، الذي يحتوي على حالة خروج آخر أمر مُنفَّذ. يمكنك رؤية ذلك في المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_15">
<span class="pln">$ true; echo $?
0
$ false; echo $?
1</span></pre>

<p>
	تذكَّر أنَّ الأمرَين <span style="font-family:courier new,courier,monospace;">true</span> و <span style="font-family:courier new,courier,monospace;">false</span> لا يفعلان شيئًا سوى الانتهاء بحالة خروج تساوي 0 و 1 على التوالي وبالترتيب. وعبر استخدامهما سنرى كيف يُعيد المتغير ‎$?‎ حالة الخروج لآخر أمر مُنفَّذ.
</p>

<p>
	نستطيع كتابة السكربت بهذه الطريقة بعد التحقق من حالة الخروج:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_17">
<span class="pln"># Check the exit status

cd $some_directory
if [ "$?" = "0" ]; then
	rm *
else
	echo "Cannot change directory!" 1&gt;&amp;2
	exit 1
fi</span></pre>

<p>
	تفحصنا محتوى الأمر <span style="font-family:courier new,courier,monospace;">cd</span>، وإن كان لا يساوي الصفر، فسيطبع رسالة خطأ في مجرى الخطأ القياسي (standard error stream) وسينتهي تنفيذه مع ضبط حالة الخروج إلى 1.
</p>

<p>
	صحيح أنَّ النسخة السابقة تقدِّم حلًا لمشكلتنا، إلا أنَّ هنالك طرائق أفضل ستقلل مقدار الكتابة التي نحتاج لها. سنستخدم في المثال الآتي العبارة الشرطية <span style="font-family:courier new,courier,monospace;">if</span> مباشرةً، لأنَّها تحقق من حالة خروج الأمر الذي يليها ثم تتصرف وفقًا لذلك. يمكننا إعادة صياغة السكربت كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_19">
<span class="pln"># A better way

if cd $some_directory; then
	rm *
else
	echo "Could not change directory! Aborting." 1&gt;&amp;2
	exit 1
fi</span></pre>

<p>
	تحققنا هنا أنَّ تنفيذ الأمر <span style="font-family:courier new,courier,monospace;">cd</span> قد نجح، وبعد ذلك سينُفّذ الأمر <span style="font-family:courier new,courier,monospace;">rm</span>؛ أو ستظهر رسالة خطأ فيما عدا ذلك وينتهي البرنامج بحالة خروج تساوي 1، مما يشير إلى حدوث مشكلة أثناء التنفيذ.
</p>

<h2>
	دالة خروج عند حدوث خطأ
</h2>

<p>
	لمّا كنّا نتحقق من الأخطاء مرارًا وتكرارًا في برامجنا، فمن المعقول أن نكتب دالةً لإظهار الأخطاء، مما يوفِّر علينا بعض الكتابة ويُنمّي إحساس الكسل لدينا :-) .
</p>

<pre class="ipsCode" id="ips_uid_1444_21">
# An error exit function

error_exit()
{
	echo "$1" 1&gt;&amp;2
	exit 1
}

# Using error_exit

if cd $some_directory; then
	rm *
else
	error_exit "Cannot change directory!  Aborting."
fi</pre>

<h2>
	معاملات التحكم: "و" AND وَ "أو" OR
</h2>

<p>
	يمكننا تبسيط السكربت كثيرًا باستخدام معاملَي التحكم "<span style="font-family:courier new,courier,monospace;">AND</span>" و "<span style="font-family:courier new,courier,monospace;">OR</span>"، وسأقتبس الفقرة الآتية من صفحة دليل bash لشرح آلية عملهما:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			 
		</p>

		<p>
			"مُعاملي التحكم <span style="font-family:courier new,courier,monospace;">&amp;&amp;</span> و<span style="font-family:courier new,courier,monospace;"> ||</span> يُمثِّلان العمليتين <span style="font-family:courier new,courier,monospace;">AND</span> وَ <span style="font-family:courier new,courier,monospace;">OR</span> على التوالي وبالترتيب.
		</p>

		<p>
			لدى المعامل <span style="font-family:courier new,courier,monospace;">AND</span> الشكل الآتي:
		</p>

		<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_23">

<span class="pln">command1 &amp;&amp; command2</span></pre>

		<p>
			إذ سيُنفَّذ الأمر <span style="font-family:courier new,courier,monospace;">command2</span> إذا أعاد الأمر <span style="font-family:courier new,courier,monospace;">command1</span> حالة خروج مساوية للصفر.
		</p>

		<p>
			لمعامل <span style="font-family:courier new,courier,monospace;">OR</span> الشكل الآتي:
		</p>

		<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_25">

<span class="pln">command1 || command2</span></pre>

		<p>
			إذ سيُنفَّذ الأمر <span style="font-family:courier new,courier,monospace;">command2</span> إذا أعاد الأمر <span style="font-family:courier new,courier,monospace;">command1</span> حالة خروج غير مساوية للصفر.
		</p>

		<p>
			حالة الخروج للتعبير الحاوي على أحد المعاملَين السابقَين تساوي حالة خروج آخر أمر مُنفَّذ في ذاك التعبير."
		</p>

		<p>
			 
		</p>
	</div>
</blockquote>

<p>
	سنستعمل الأمرَين <span style="font-family:courier new,courier,monospace;">true</span> و <span style="font-family:courier new,courier,monospace;">false</span> مجددًا لكي نشاهد آلية التعامل مع <span style="font-family:courier new,courier,monospace;">AND</span> و <span style="font-family:courier new,courier,monospace;">OR</span> عمليًا:
</p>

<pre class="ipsCode" id="ips_uid_1444_27">
$ true || echo "echo executed"
$ false || echo "echo executed"
echo executed
$ true &amp;&amp; echo "echo executed"
echo executed
$ false &amp;&amp; echo "echo executed"
$</pre>

<p>
	باستخدام هذه التقنية، يمكننا إعادة كتابة نسخة مختصرة أكثر من السكربت السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_29">
<span class="pln"># Simplest of all

cd $some_directory || error_exit "Cannot change directory! Aborting"
rm *</span></pre>

<p>
	إن لم يكن إنهاء البرنامج مطلوبًا، فيمكننا كتابة السكربت بالصيغة الآتية:
</p>

<pre class="ipsCode" id="ips_uid_1444_31">
# Another way to do it if exiting is not desired

cd $some_directory &amp;&amp; rm *</pre>

<p>
	صحيحٌ أننا أخذنا جميع الاحتياطات الممكنة في مثال <span style="font-family:courier new,courier,monospace;">cd</span>، إلا أنني أود أن أشير أنَّ الشيفرة يمكن أن تتعرض للمشاكل البرمجية الشائعة، خصوصًا إذا كُتِبَ اسم المتغير الذي يحتوي على مسار المجلد الذي نريد حذف محتوياته بشكلٍ خاطئ. ففي هذه الحالة ستضع الصَدَفة قيمةً فارغةً بدلًا من اسم المتغير وسينتج تنفيذ الأمر <span style="font-family:courier new,courier,monospace;">cd</span>، لكنه سينتقل إلى مجلد المنزل للمستخدم الحالي، ثم سيحذف كل ما فيه!
</p>

<h2>
	تحسين دالة الخروج عند حدوث خطأ
</h2>

<p>
	هنالك عددٌ من التحسينات التي نستطيع إجراءها على الدالة <span style="font-family:courier new,courier,monospace;">error_exit</span>، أود أن أضع اسم البرنامج في رسالة الخطأ كي أوضِّح من أين تأتي رسالة الخطأ؛ وذلك مهمٌ خصوصًا في السكربتات الكبيرة والمعقدة التي تُستدعى فيها سكربتات داخل سكربتات… لاحظ أيضًا تضمين متغير البيئة <span style="font-family:courier new,courier,monospace;">LINENO</span> الذي سيساعد في تحديد السطر الذي حدثت فيه المشكلة.
</p>

<pre class="ipsCode" id="ips_uid_1444_33">
#!/bin/bash

# A slicker error handling routine

# I put a variable in my scripts named PROGNAME which
# holds the name of the program being run.  You can get this
# value from the first item on the command line ($0).

PROGNAME=$(basename $0)

error_exit()
{

#	----------------------------------------------------------------
#	Function for exit due to fatal program error
#		Accepts 1 argument:
#			string containing descriptive error message
#	----------------------------------------------------------------


	echo "${PROGNAME}: ${1:-"Unknown Error"}" 1&gt;&amp;2
	exit 1
}

# Example call of the error_exit function.  Note the inclusion
# of the LINENO environment variable.  It contains the current
# line number.

echo "Example of error with line number and message"
error_exit "$LINENO: An error has occurred."</pre>

<p>
	استخدام الحاضنات ({}) داخل الدالة <span style="font-family:courier new,courier,monospace;">error_exit</span> هو مثالٌ عن "توسعة المعاملات" (parameter expansion)، يمكنك وضع حاضنات حول اسم المتغير (كما في <span style="font-family:courier new,courier,monospace;">{‎${PROGNAME</span>) إذا أردت عزل المتغير عمّا حوله من نصوص. يُفضِّل البعض وضع الحاضنات حول كل متغير، وهذا الأمر منوطٌ بك.
</p>

<p>
	الشيء الآخر الذي أريد الإشارة إليه هو <span style="font-family:courier new,courier,monospace;">{"‎${1:- "Unknown Error</span> الذي يعني أنَّه لو لم يكن المعامل 1 (أي ‎<span style="font-family:courier new,courier,monospace;">$1</span>) مُعرَّفًا، فضع السلسلة النصية "Unknown Error" مكانه. يمكن إجراء الكثير من عمليات معالجة النصوص باستخدام توسعة المعاملات.
</p>

<h2>
	الإشارات Signals
</h2>

<p>
	لا تستطيع اعتبار أنَّ الأخطاء هي المُسبِّب الوحيد لإنهاء البرنامج على نحوٍ غير متوقع، فعليك أن تحتاط من الإشارات (signals) أيضًا. ليكن لديك المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_36">
<span class="pln">#!/bin/bash

echo "this script will endlessly loop until you stop it"
while true; do
	: # Do nothing
done</span></pre>

<p>
	بعد أن تُشغِّل هذا السكربت، فسيبدو وكأنَّه علّق، لكنه -مثل أغلبية البرامج التي تُعلِّق- قد دخل في حلقة تكرار ولم يخرج منها. فالسكربت في مثالنا ينتظر أن يُعيد الأمر <span style="font-family:courier new,courier,monospace;">true</span> حالة خروج لا تساوي الصفر، وهذا لن يحدث أبدًا. وسيستمر تنفيذ السكربت إلى أن تُرسِل الصَدَفة bash إشارةً له لإيقافه. يمكنك إرسال إشارة بالضغط على<span style="font-family:courier new,courier,monospace;"> Ctrl+c</span> التي تُسمى <span style="font-family:courier new,courier,monospace;">SIGINT</span> (مختصرة من SIGnal INTerrupt).
</p>

<h2>
	إنهاء البرامج التي تستقبل إشارات بشكل سليم
</h2>

<p>
	حسنًا، يمكن أن تأتي إشارة وتؤدي إلى إنهاء تنفيذ السكربت، لكن لماذا نهتم بذلك؟ لا يؤدي إنهاء السكربت عبر الإشارات في العديد من الحالات إلى مشاكل، لكنها تحتاج إلى معالجة في بعض الحالات.
</p>

<p>
	لننظر إلى مثالٍ آخر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_38">
<span class="pln">#!/bin/bash

# Program to print a text file with headers and footers

TEMP_FILE=/tmp/printfile.txt

pr $1 &gt; $TEMP_FILE

echo -n "Print file? [y/n]: "
read
if [ "$REPLY" = "y" ]; then
	lpr $TEMP_FILE
fi</span></pre>

<p>
	يُعالِج السكربت السابق ملفًا نصيًا مُمَرَّرًا كوسيط في سطر الأوامر عبر الأمر <span style="font-family:courier new,courier,monospace;">pr</span> الذي يُخزِّن الناتج في ملف مؤقت (temporary file)، ثم سيسأل المستخدم عمّا إذا كان يريد طباعة الملف، فلو وافق المستخدم عبر كتابة y فسيُمرَّر الملف المؤقت إلى الأمر <span style="font-family:courier new,courier,monospace;">lpr</span> للطباعة (يمكنك وضع الأمر <span style="font-family:courier new,courier,monospace;">less</span> بدلًا من <span style="font-family:courier new,courier,monospace;">lpr</span> إذا لم تكن لديك طابعة موصولة بحاسوبك).
</p>

<p>
	عليّ أن أعترف لك أنَّ السكربت السابق فيه العديد من المشاكل التصميمية؛ وعلى الرغم من استخدامه لاسم الملف المُمرَّر عبر سطر الأوامر، لكنه لا يتحقق أنَّ القيمة فارغة، ولا يتحقق إن كان الملف موجودًا فعلًا. لكن الفكرة التي أريد التركيز عليها هي أنَّه عندما ينتهي تنفيذ السكربت، فسيُبقي خلفه ملفًا مؤقتًا.
</p>

<p>
	من المستحسن أن نحذف الملف المؤقت ‎<span style="font-family:courier new,courier,monospace;">$TEMP_FILE</span> عند انتهاء تنفيذ السكربت، ويتم هذا بسهولة بإضافة السطر الآتي في نهاية السكربت:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_40">
<span class="pln">rm $TEMP_FILE</span></pre>

<p>
	قد تظن أننا حللنا المشكلة، لكن ماذا سيحدث لو ضغط المستخدم على<span style="font-family:courier new,courier,monospace;"> Ctrl+c</span> عندما تظهر الرسالة "<span style="font-family:courier new,courier,monospace;">Print file? [y/n]:</span>‎" سينتهي تنفيذ السكربت عند الأمر <span style="font-family:courier new,courier,monospace;">read</span> ولن يُنفَّذ الأمر <span style="font-family:courier new,courier,monospace;">rm</span> أبدًا. سنحتاج إذًا إلى طريقة لمعالجة الإشارات مثل <span style="font-family:courier new,courier,monospace;">SIGINT</span> عندما يضغط المستخدم على<span style="font-family:courier new,courier,monospace;"> Ctrl+c</span>.
</p>

<p>
	لحسن الحظ، توفِّر bash طريقةً لتنفيذ الأوامر فيما إذا استقبِلَت إشارةٌ ما.
</p>

<h2>
	الأمر trap
</h2>

<p>
	يسمح لك الأمر <span style="font-family:courier new,courier,monospace;">trap</span> بتنفيذ أمر عندما يستقبل سكربتك إشارةً. يعمل هذا الأمر كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_42">
<span class="pln">trap arg signals</span></pre>

<p>
	حيث <span style="font-family:courier new,courier,monospace;">signals</span> هي قائمة بالإشارات التي تريد «اعتراضها» أو معالجتها، و <span style="font-family:courier new,courier,monospace;">arg</span> هو الأمر التي سيُنفَّذ عندما تُستقبَل واحدة من الإشارات المُحدَّدة. يمكننا التعامل مع الإشارات في سكربت الطباعة السابق كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_44">
<span class="pln">#!/bin/bash

# Program to print a text file with headers and footers

TEMP_FILE=/tmp/printfile.txt

trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM

pr $1 &gt; $TEMP_FILE

echo -n "Print file? [y/n]: "
read
if [ "$REPLY" = "y" ]; then
	lpr $TEMP_FILE
fi
rm $TEMP_FILE</span></pre>

<p>
	أضفنا الأمر <span style="font-family:courier new,courier,monospace;">trap</span> الذي سيُنفِّذ الأمر <span style="font-family:courier new,courier,monospace;">rm $TEMP_FILE</span> إذا استقبل السكربت إحدى الإشارات المذكورة، التي هي أكثر الإشارات التي ستواجهها، لكن هنالك المزيد منها التي تستطيع ذكرها أيضًا. انظر ناتج الأمر<span style="font-family:courier new,courier,monospace;"> trap -l </span>لرؤية القائمة الكاملة. يمكنك أيضًا ذكر الإشارات بأرقامها بدلًا من أسمائها.
</p>

<h3>
	الإشارة 9 التي لا ترحم!
</h3>

<p>
	هنالك إشارة لا تستطيع التعامل معها داخل السكربت: إشارة <span style="font-family:courier new,courier,monospace;">SIGKILL</span> أو الإشارة رقم 9. ستُنهي النواة أيّ عملية تُرسَل لها هذه الإشارة مباشرةً دون العودة إلى البرنامج أو السماح له بإجراء أيّ عملية لمعالجة الإشارة. ولأنه هذه الإشارة تُنهي البرامج التي تُعلِّق أو لا تستجيب، فربما تظن أنَّها أسهل طريقة لإنهاء برنامج ما. وقد ترى الأمر الآتي عندما يأتي ذكر الإشارة <span style="font-family:courier new,courier,monospace;">SIGKILL</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_46">
<span class="pln">kill -9</span></pre>

<p>
	وعلى الرغم من أنَّ هذه الإشارة تُتِمُّ عملها بسرعة وسهولة، لكن تذكَّر أنَّ البرنامج لن يستطيع معالجة هذه الإشارة، ولا بأس في ذلك في بعض الحالات؛ لكن قد يُسبِّب مشاكل في بعضها الآخر. حيث تُنشِئ بعض البرامج المعقدة (وحتى بعض البرامج غير المعقدة) ملفات اسمها lock files لمنع تشغيل عدِّة نسخ من نفس البرنامج في نفس الوقت. فعندما تُرسَل إشارة <span style="font-family:courier new,courier,monospace;">SIGKILL</span> إلى برنامج يستخدم lock files، فلن يكون لديه فرصة لحذف ذاك الملف؛ وسيؤدي وجود ذاك الملف إلى منع تشغيل البرنامج إلى أن يُحذَف يدويًا.
</p>

<p>
	استعمل <span style="font-family:courier new,courier,monospace;">SIGKILL</span> كملاذٍ أخيرٍ لك.
</p>

<h2>
	دالة clean_up
</h2>

<p>
	صحيحٌ أنَّ الأمر <span style="font-family:courier new,courier,monospace;">trap</span> حلّ المشكلة، لكننا لاحظنا بعض المحدوديات؛ خصوصًا أنَّه لا يقبل إلا سلسلةً نصيةً وحيدةً تحتوي الأمر الذي سيُنفَّذ عندما تُستقبَل الإشارة. يمكنك الالتفاف على هذه المحدودية بوضع ; بين عدِّة أوامر، إلا أنَّ هذه الطريقة بشعة المظهر. فمن الأفضل إنشاء دالة ستُستدعى عندما ينتهي تنفيذ السكربت. أُسميّ هذه الدالة عادةً <span style="font-family:courier new,courier,monospace;">clean_up</span>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_48">
<span class="pln">#!/bin/bash

# Program to print a text file with headers and footers

TEMP_FILE=/tmp/printfile.txt

clean_up() {

	# Perform program exit housekeeping
	rm $TEMP_FILE
	exit
}

trap clean_up SIGHUP SIGINT SIGTERM

pr $1 &gt; $TEMP_FILE

echo -n "Print file? [y/n]: "
read
if [ "$REPLY" = "y" ]; then
	lpr $TEMP_FILE
fi
clean_up</span></pre>

<p>
	يمكن استعمال دالة <span style="font-family:courier new,courier,monospace;">clean_up</span> في البُنى التي تهتم بمعالجة الأخطاء. فيجب على أيّة حال أن "تُنظِّف" ما خلّفه السكربت بعد انتهائه (لأي سببٍ كان). هذه هي النسخة النهائية من برنامجنا التي حسّنّا فيها معالجة الأخطاء والإشارات:
</p>

<pre class="ipsCode" id="ips_uid_1444_50">
#!/bin/bash

# Program to print a text file with headers and footers

# Usage: printfile file

# Create a temporary file name that gives preference
# to the user's local tmp directory and has a name
# that is resistant to "temp race attacks"

if [ -d "~/tmp" ]; then
	TEMP_DIR=~/tmp
else
	TEMP_DIR=/tmp
fi
TEMP_FILE=$TEMP_DIR/printfile.$$.$RANDOM
PROGNAME=$(basename $0)

usage() {

	# Display usage message on standard error
	echo "Usage: $PROGNAME file" 1&gt;&amp;2
}

clean_up() {

	# Perform program exit housekeeping
	# Optionally accepts an exit status
	rm -f $TEMP_FILE
	exit $1
}

error_exit() {

	# Display error message and exit
	echo "${PROGNAME}: ${1:-"Unknown Error"}" 1&gt;&amp;2
	clean_up 1
}

trap clean_up SIGHUP SIGINT SIGTERM

if [ $# != "1" ]; then
	usage
	error_exit "one file to print must be specified"
fi
if [ ! -f "$1" ]; then
	error_exit "file $1 cannot be read"
fi

pr $1 &gt; $TEMP_FILE || error_exit "cannot format file"

echo -n "Print file? [y/n]: "
read
if [ "$REPLY" = "y" ]; then
	lpr $TEMP_FILE || error_exit "cannot print file"
fi
clean_up</pre>

<h2>
	الطريقة المثالية لإنشاء ملفات مؤقتة
</h2>

<p>
	هنالك عدِّة إجراءات يمكننا اتخاذها لتأمين الملف المؤقت الذي استخدمه السكربت. من تقاليد نظام يونكس استخدام المجلد <span style="font-family:courier new,courier,monospace;">‎/tmp</span> لتخزين الملفات المؤقتة التي تستعملها البرامج. يمكن للجميع الكتابة إلى ذاك المجلد، وقد يُسبِّب ذلك لك بعض المخاوف الأمنية. تجنّب كتابة الملفات في مجلد <span style="font-family:courier new,courier,monospace;">‎/tmp</span> إن كان ذلك ممكنًا. التقنية المُستحسنة هي كتابة الملفات إلى مجلد محلي مثل <span style="font-family:courier new,courier,monospace;">‎~/tmp</span> (أي مجلد <span style="font-family:courier new,courier,monospace;">tmp</span> الموجود في مجلد المنزل للمستخدم المُنفِّذ للسكربت)؛ وإن كان لا بُد، فعليك اتخاذ بعض الخطوات للتأكد أن أسماء الملفات المُخزَّنة في مجلد ‎<span style="font-family:courier new,courier,monospace;">‎/tmp</span> غير متوقعة؛ حيث تسمح أسماء الملفات المتوقعة للمخترقين أن يُنشِئوا وصلات رمزية إلى ملفات أخرى التي يريدون منك أن تكتب فوقها.
</p>

<p>
	الاسم الجيد للملف المؤقت هو الاسم الذي يسمح لك بمعرفة مَن الذي كتب الملف، ولكنه ليس متوقعًا بشكلٍ كامل. استخدمنا السطر الآتي في السكربت أعلاه لإنشاء اسم الملف المؤقت ‎<span style="font-family:courier new,courier,monospace;">$TEMP_FILE</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1444_52">
<span class="pln">TEMP_FILE=$TEMP_DIR/printfile.$$.$RANDOM</span></pre>

<p>
	سيحتوي المتغير <span style="font-family:courier new,courier,monospace;">‎$TEMP_DIR</span> على ‎<span style="font-family:courier new,courier,monospace;">‎/tmp</span> أو ‎<span style="font-family:courier new,courier,monospace;">~/tmp</span> اعتمادًا على توفر المجلد <span style="font-family:courier new,courier,monospace;">~/tmp</span>، ومن الشائع تضمين اسم البرنامج في اسم الملف، وهذا هو سبب وضعنا للكلمة "printfile". ثم استخدمنا متغير الصَدَفة $$ لتضمين مُعرِّف العملية (<abbr title="Process IDentifier | معرّف العملية أو البرنامج"><abbr title="Process IDentifier | معرّف العملية أو البرنامج"><abbr title="Process IDentifier | معرّف العملية أو البرنامج">PID</abbr></abbr></abbr>) الخاص بالبرنامج. وهذا سيُحدِّد تمامًا ما هي العملية المسؤولة عن الملف. وبالطبع لا نستطيع أن نعتبر أنَّ رقم العملية كافٍ لجعل اسم الملف غير متوقع؛ لهذا أضفنا متغير الصَدَفة ‎<span style="font-family:courier new,courier,monospace;">$RANDOM</span> لتضمين رقم عشوائي في اسم الملف. وبالآلية السابقة، أنشأنا اسمًا لملفٍ مؤقتٍ سهلُ التعرف وغير متوقع.
</p>

<h2>
	خاتمة
</h2>

<p>
	حسنًا، لقد أنهينا هذه السلسلة، أرجو أن تكون قد وجدتها مفيدةً ومسلية في آن واحد. وأنصحك بإكمال مسيرتك في سطر الأوامر وسكربتات الصَدَفة بقراءة كتاب <a href="http://sourceforge.net/projects/omlx/files/open%20books/TLCL/The_Linux_Command_Line-arabic-14.07.pdf/download" rel="external nofollow">سطر أوامر لينُكس</a> لمترجمه عبد اللطيف ايمش.
</p>

<p>
	ترجمة -وبتصرّف- للمقالين <a href="http://linuxcommand.org/lc3_wss0140.php" rel="external nofollow">Errors And Signals And Traps (Oh My!) - Part 1</a> و <a href="http://linuxcommand.org/lc3_wss0150.php" rel="external nofollow">Errors And Signals And Traps (Oh, My!) - Part 2</a> لصاحبهما William Shotts.
</p>
]]></description><guid isPermaLink="false">274</guid><pubDate>Wed, 22 Jun 2016 08:11:04 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x628;&#x646;&#x649; &#x627;&#x644;&#x62A;&#x62D;&#x643;&#x645; (Flow Control) &#x641;&#x64A; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts) - &#x627;&#x644;&#x62C;&#x632;&#x621; 3</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-flow-control-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-3-r273/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-for-loop.png.4cdf4e90a06b58577482f37659171619.png" /></p>

<p>
	بعد أن تعلمنا التعامل مع <a href="https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%88%D8%B6%D8%B9%D9%8A%D8%A9-positional-parameters-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r271/" rel="">المعاملات الموضعية (Positional parameters)</a> في الدرس السابق، حان الوقت الآن لشرح آخر بُنية من بُنى التحكم: <span style="font-family:courier new,courier,monospace;">for</span>.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17884" data-unique="epa7yuvi0" src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-for-loop.png.711c6db2d211f37f0860564e994eeeb4.png" alt="shell-script-for-loop.png"></p>

<p>
	وكما في البنيتين <span style="font-family:courier new,courier,monospace;">while</span> و <span style="font-family:courier new,courier,monospace;">until</span>، تُستعمَل <span style="font-family:courier new,courier,monospace;">for</span> لإنشاء حلقات تكرار. الشكل العام لحلقة <span style="font-family:courier new,courier,monospace;">for</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_8">
<span class="pln">for variable in words; do
    commands
done</span></pre>

<p>
	الخلاصة هي أنَّ <span style="font-family:courier new,courier,monospace;">for</span> تُسنِد كلمةً من قائمة الكلمات إلى متغيّرٍ معيّن، ثم تُنفِّذ الأوامر الموجودة داخل الحلقة، ثم تكرر ذلك إلى أن تُستعمَل جميع الكلمات الموجودة في القائمة. هذا مثالٌ عنها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_10">
<span class="pln">#!/bin/bash

for i in word1 word2 word3; do
    echo $i
done</span></pre>

<p>
	أُسنِدَت -في بادئ الأمر- القيمة <span style="font-family:courier new,courier,monospace;">word1</span> إلى المتغير i، ثم نُفِّذ الأمر <span style="font-family:courier new,courier,monospace;">echo $i</span>، ثم أُسنِدَت القيمة <span style="font-family:courier new,courier,monospace;">word2</span> إلى المتغير <span style="font-family:courier new,courier,monospace;">i</span>، ثم نُفِّذ الأمر <span style="font-family:courier new,courier,monospace;">echo $i</span>، وهكذا، إلى أن تُسنَد جميع الكلمات إلى المتغير <span style="font-family:courier new,courier,monospace;">i</span>. 
</p>

<p>
	الشيء المثير للاهتمام في <span style="font-family:courier new,courier,monospace;">for</span> هو تنوع الطرائق التي تستطيع فيها بناء قائمة الكلمات، حيث يمكن استخدام جميع أنواع التوسعات (expansions). سنولِّد قائمة الكلمات في المثال الآتي باستخدام تعويض الأوامر (command substitution):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_12">
<span class="pln">#!/bin/bash

count=0
for i in $(cat ~/.bash_profile); do
    count=$((count + 1))
    echo "Word $count ($i) contains $(echo -n $i | wc -c) characters"
done</span></pre>

<p>
	قمنا في المثال السابق بإحصاء عدد الكلمات في ملف ‎<span style="font-family:courier new,courier,monospace;">.bash_profile</span>، ثم أظهرنا عدد الحروف في كل كلمة. 
</p>

<p>
	حسنًا، ما علاقة ذلك بالمعاملات الموضعية؟ حسنًا، يمكن استخدام المعاملات الموضعية كقائمة بالكلمات التي ستمرّ عليها الحلقة <span style="font-family:courier new,courier,monospace;">for</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_14">
<span class="pln">#!/bin/bash

for i in "$@"; do
    echo $i
done</span></pre>

<p>
	المتغير "<span style="font-family:courier new,courier,monospace;">@</span>" هو متغيرٌ خاصٌ بالصَدَفة ويحتوي على قائمة بوسائط سطر الأوامر. تُستعمَل هذه التقنية عادةً لمعالجة قائمة ملفات عبر سطر الأوامر. هذا مثالٌ آخر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_16">
<span class="pln">#!/bin/bash

for filename in "$@"; do
    result=
    if [ -f "$filename" ]; then
        result="$filename is a regular file"
    else
        if [ -d "$filename" ]; then
            result="$filename is a directory"
        fi
    fi
    if [ -w "$filename" ]; then
        result="$result and it is writable"
    else
        result="$result and it is not writable"
    fi
    echo "$result"
done</span></pre>

<p>
	جرِّب السكربت السابق، ومرِّر إليه قائمةً بعدِّة ملفات، أو استعمل محرفًا بديلًا مثل <span style="font-family:courier new,courier,monospace;">*</span> وانظر إلى مخرجاته. 
</p>

<p>
	هذا سكربتٌ آخر يُقارِن الملفات الموجودة في مجلدين، ويظهِر قائمة بالملفات الموجودة في المجلد الأول وغير الموجودة في المجلد الثاني:
</p>

<pre class="ipsCode" id="ips_uid_2199_18">
#!/bin/bash

# cmp_dir - program to compare two directories

# Check for required arguments
if [ $# -ne 2 ]; then
    echo "usage: $0 directory_1 directory_2" 1&gt;&amp;2
    exit 1
fi

# Make sure both arguments are directories
if [ ! -d $1 ]; then
    echo "$1 is not a directory!" 1&gt;&amp;2
    exit 1
fi

if [ ! -d $2 ]; then
    echo "$2 is not a directory!" 1&gt;&amp;2
    exit 1
fi

# Process each file in directory_1, comparing it to directory_2
missing=0
for filename in $1/*; do
    fn=$(basename "$filename")
    if [ -f "$filename" ]; then
        if [ ! -f "$2/$fn" ]; then
            echo "$fn is missing from $2"
            missing=$((missing + 1))
        fi
    fi
done
echo "$missing files missing"</pre>

<p>
	لنوظِّف ما سبق في مثالٌ عملي. لنحاول تحسين الدالة <span style="font-family:courier new,courier,monospace;">home_space</span> في السكربت الذي نبنيه لكي تُخرِج المزيد من المعلومات. كانت النسخة القديمة من الدالة تبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_20">
<span class="pln">home_space()
{
    # Only the superuser can get this information

    if [ "$(id -u)" = "0" ]; then
    echo "</span><span class="tag">&lt;h2&gt;</span><span class="pln">Home directory space by user</span><span class="tag">&lt;/h2&gt;</span><span class="pln">"
    echo "</span><span class="tag">&lt;pre&gt;</span><span class="pln">"
    echo "Bytes Directory"
        du -s /home/* | sort -nr
    echo "</span><span class="tag">&lt;/pre&gt;</span><span class="pln">"
    fi

}   # end of home_space</span></pre>

<p>
	هذه هي النسخة الحديثة منها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_22">
<span class="pln">home_space()
{
    echo "</span><span class="tag">&lt;h2&gt;</span><span class="pln">Home directory space by user</span><span class="tag">&lt;/h2&gt;</span><span class="pln">"
    echo "</span><span class="tag">&lt;pre&gt;</span><span class="pln">"
    format="%8s%10s%10s   %-s\n"
    printf "$format" "Dirs" "Files" "Blocks" "Directory"
    printf "$format" "----" "-----" "------" "---------"
    if [ $(id -u) = "0" ]; then
        dir_list="/home/*"
    else
        dir_list=$HOME
    fi
    for home_dir in $dir_list; do
        total_dirs=$(find $home_dir -type d | wc -l)
        total_files=$(find $home_dir -type f | wc -l)
        total_blocks=$(du -s $home_dir)
        printf "$format" $total_dirs $total_files $total_blocks
    done
    echo "</span><span class="tag">&lt;/pre&gt;</span><span class="pln">"

}   # end of home_space</span></pre>

<p>
	تتضمن هذه النسخة المُحسَّنة أمرًا جديدًا هو <span style="font-family:courier new,courier,monospace;">printf</span>، الذي يُستخدم لتنسيق المُخرجات بناءً على محتويات "عبارة التنسيق" (format string). تنحدر أصول الأمر <span style="font-family:courier new,courier,monospace;">printf</span> من لغة البرمجة C وهو موجودٌ أيضًا في لغاتٍ برمجيةٍ أخرى مثل C++‎ و Perl و awk و java و PHP وبالطبع bash.
</p>

<p>
	هنالك أمرٌ آخر جديد هو الأمر <span style="font-family:courier new,courier,monospace;">find</span>، الذي يُستخدم للبحث عن ملفات أو مجلدات تُطابِق معيارًا أو مقياسًا محدَّدًا (criteria). 
</p>

<p>
	استخدمنا الأمر <span style="font-family:courier new,courier,monospace;">find</span> في الدالة <span style="font-family:courier new,courier,monospace;">home_space</span> لعرض قائمة بالمجلدات والملفات العادية الموجودة في مجلد المنزل، ثم أحصينا عدد الملفات والمجلدات باستخدام الأمر <span style="font-family:courier new,courier,monospace;">wc</span> (تذكَّر أنَّه اختصار للعبارة "Word Count").
</p>

<p>
	النقطة المثيرة للاهتمام في دالة <span style="font-family:courier new,courier,monospace;">home_space</span> المُعدَّلة هي كيفية تعاملنا مع مشكلة عدم السماح بالوصول إلى مجلدات المنزل من المستخدمين العاديين، يمكنك ملاحظة أنَّنا اختبرنا إن كان المستخدم هو الجذر بوساطة <span style="font-family:courier new,courier,monospace;">id</span> ثم -اعتمادًا على ناتج الاختبار- أسندنا سلاسل نصية مختلفة إلى المتغير <span style="font-family:courier new,courier,monospace;">dir_list</span>، الذي سيُمثِّل قائمة الكلمات لحلقة <span style="font-family:courier new,courier,monospace;">for</span> التي تليه. وبهذه الطريقة، إذا شغَّل مستخدمُ عاديٌ السكربت، فستُعرض معلومات عن مجلد المنزل الخاص به فقط. <br>
	موضوعٌ آخر يمكننا توظيف حلقة <span style="font-family:courier new,courier,monospace;">for</span> فيه هو الدالة <span style="font-family:courier new,courier,monospace;">system_info</span> التي لم نكملها بعد. يمكننا كتابتها كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2199_24">
<span class="pln">system_info()
{
    # Find any release files in /etc

    if ls /etc/*release 1&gt;/dev/null 2&gt;&amp;1; then
        echo "</span><span class="tag">&lt;h2&gt;</span><span class="pln">System release info</span><span class="tag">&lt;/h2&gt;</span><span class="pln">"
        echo "</span><span class="tag">&lt;pre&gt;</span><span class="pln">"
        for i in /etc/*release; do

            # Since we can't be sure of the
            # length of the file, only
            # display the first line.

            head -n 1 $i
        done
        uname -orp
        echo "</span><span class="tag">&lt;/pre&gt;</span><span class="pln">"
    fi

}   # end of system_info</span></pre>

<p>
	حدَّدنا في بادئ الأمر إن كانت هنالك ملفات <span style="font-family:courier new,courier,monospace;">release</span> لكي نعالجها. تحتوي ملفات <span style="font-family:courier new,courier,monospace;">release</span> على اسم التوزيعة وإصدارها. وهي موجودة في مجلد ‎<span style="font-family:courier new,courier,monospace;">/etc</span>. ولكي نكتشف وجودها، سنستعمل الأمر <span style="font-family:courier new,courier,monospace;">ls</span> لكننا لسنا مهتمين بمخرجات الأمر، وإنما بحالة الخروج، التي ستكون مساوية للصفر (true) إن وُجِدَت أيّة ملفات. 
</p>

<p>
	الخطوة الآتية هي طباعة شيفرة HTML لهذا القسم من الصفحة؛ ولمّا كنا نعلم أنَّ هنالك عدِّة ملفات <span style="font-family:courier new,courier,monospace;">release</span> لكي نعالجها، فسنستخدم حلقة <span style="font-family:courier new,courier,monospace;">for</span> للمرور على كلٍ واحدٍ منها. ثم سنستعمل الأمر <span style="font-family:courier new,courier,monospace;">head</span> في داخل الحلقة للحصول على السطر الأول من كل ملف. 
</p>

<p>
	في النهاية، استعملنا الأمر <span style="font-family:courier new,courier,monospace;">uname</span> مع الخيارات o و r و p للحصول على بعض المعلومات الإضافية حول النظام. 
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://linuxcommand.org/lc3_wss0130.php" rel="external nofollow">Flow Control - Part 3</a> لصاحبه William Shotts.
</p>
]]></description><guid isPermaLink="false">273</guid><pubDate>Thu, 16 Jun 2016 13:53:35 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x639;&#x627;&#x645;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x648;&#x636;&#x639;&#x64A;&#x629; (Positional parameters) &#x641;&#x64A; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts)</title><link>https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%88%D8%B6%D8%B9%D9%8A%D8%A9-positional-parameters-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r271/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-scripts-positional-parameters.png.fa7df85e6e105b0ca68752710d51ab1f.png" /></p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17698" data-unique="ip4hsqjd2" src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-scripts-positional-parameters.png.ddd3809551e16357cb8f3003ce918239.png" alt="shell-scripts-positional-parameters.png"></p>

<p>
	لدينا السكربت التالي:
</p>

<pre class="ipsCode" id="ips_uid_2413_8">
#!/bin/bash

# sysinfo_page - A script to produce a system information HTML file

##### Constants

TITLE="System Information for $HOSTNAME"
RIGHT_NOW=$(date +"%x %r %Z")
TIME_STAMP="Updated on $RIGHT_NOW by $USER"

##### Functions

system_info()
{
    echo "&lt;h2&gt;System release info&lt;/h2&gt;"
    echo "&lt;p&gt;Function not yet implemented&lt;/p&gt;"

}   # end of system_info


show_uptime()
{
    echo "&lt;h2&gt;System uptime&lt;/h2&gt;"
    echo "&lt;pre&gt;"
    uptime
    echo "&lt;/pre&gt;"

}   # end of show_uptime


drive_space()
{
    echo "&lt;h2&gt;Filesystem space&lt;/h2&gt;"
    echo "&lt;pre&gt;"
    df
    echo "&lt;/pre&gt;"

}   # end of drive_space


home_space()
{
    # Only the superuser can get this information

    if [ "$(id -u)" = "0" ]; then
        echo "&lt;h2&gt;Home directory space by user&lt;/h2&gt;"
        echo "&lt;pre&gt;"
        echo "Bytes Directory"
        du -s /home/* | sort -nr
        echo "&lt;/pre&gt;"
    fi

}   # end of home_space



##### Main

cat &lt;&lt;- _EOF_
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;$TITLE&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;h1&gt;$TITLE&lt;/h1&gt;
      &lt;p&gt;$TIME_STAMP&lt;/p&gt;
      $(system_info)
      $(show_uptime)
      $(drive_space)
      $(home_space)
  &lt;/body&gt;
  &lt;/html&gt;
_EOF_</pre>

<p>
	تعمل أغلبية الميزات التي فيه عملًا سليمًا، لكن هنالك بعض الميزات التي أرغب بإضافتها: 
</p>

<ol>
<li>
		أريد تحديد اسم ملف الخرج في سطر الأوامر، بالإضافة إلى ضبط اسم ملف افتراضي إن لم يُحدِّد المستخدم اسم الملف. 
	</li>
	<li>
		أريد توفير نمط تفاعلي يسأل المستخدم عن اسم الملف ويُحذِّر المستخدم إن كان الملف موجودًا ويسأله إذا كان يريد إعادة الكتابة فوقه. 
	</li>
	<li>
		من البديهي توفر خيار للمساعدة يعرض رسالة توضِّح كيفية الاستخدام. 
	</li>
</ol>
<p>
	تتطلب جميع الميزات السابقة استخدام الخيارات والوسائط في سطر الأوامر، وتوفِّر لنا الصَدَفة المعاملات الموضعية (positional parameters) للوصول إليها. المعاملات الموضعية هي سلسلة من المتغيرات (من ‎$0‎ إلى ‎$9) التي تحتوي على قيم الوسائط في سطر الأوامر. 
</p>

<p>
	لنتخيل تنفيذ الأمر الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_10">
<span class="pln">$ some_program word1 word2 word3</span></pre>

<p>
	إذا كان <span style="font-family:courier new,courier,monospace;">some_program</span> سكربت صَدَفة، فسيستطيع قراءة كل عنصر من عناصر السطر السابق لأنَّ المعاملات الموضعية تحتوي على ما يلي: 
</p>

<ul>
<li>
		سيحتوي المتغير ‎<span style="font-family:courier new,courier,monospace;">$0</span> على "some_program"
	</li>
	<li>
		سيحتوي المتغير ‎<span style="font-family:courier new,courier,monospace;">$1</span> على "word1" 
	</li>
	<li>
		سيحتوي المتغير ‎<span style="font-family:courier new,courier,monospace;">$2</span> على "word2"
	</li>
	<li>
		سيحتوي المتغير ‎<span style="font-family:courier new,courier,monospace;">$3</span> على "word3
	</li>
</ul>
<p>
	هذا هو السكربت الذي تستطيع تجربته لتشاهد ما سبق عمليًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_12">
<span class="pln">#!/bin/bash

echo "Positional Parameters"
echo '$0 = ' $0
echo '$1 = ' $1
echo '$2 = ' $2
echo '$3 = ' $3</span></pre>

<h2>
	اكتشاف وجود وسائط في سطر الأوامر
</h2>

<p>
	عليك عادةً التحقق من وجود وسائط لكي يتصرَّف برنامجك وفقها؛ وهنالك طريقتان لفعل ذلك. أولهما هي التحقق من احتواء المتغير ‎<span style="font-family:courier new,courier,monospace;">$1</span> لأي قيمة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_14">
<span class="pln">#!/bin/bash

if [ "$1" != "" ]; then
    echo "Positional parameter 1 contains something"
else
    echo "Positional parameter 1 is empty"
fi</span></pre>

<p>
	تحتوي الصَدَفة على متغير اسمه<span style="font-family:courier new,courier,monospace;"> ‎$#‎ </span>الذي يحتوي على عدد الوسائط في سطر الأوامر، وهذه هي الطريقة الثانية.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_16">
<span class="pln">#!/bin/bash

if [ $# -gt 0 ]; then
    echo "Your command line contains $# arguments"
else
    echo "Your command line contains no arguments"
fi</span></pre>

<h2>
	خيارات سطر الأوامر
</h2>

<p>
	العديد من البرامج، وخصوصًا تلك التي أتت من مشروع GNU، تدعم خيارات طويلة ومختصرة لسطر الأوامر. فمثلًا، ستستعمل الخيار المختصر <span style="font-family:courier new,courier,monospace;">‎-h</span> لعرض رسالة المساعدة لأغلبية البرامج أو الخيار الطويل ‎<span style="font-family:courier new,courier,monospace;">--help</span>. تُسبَق أسماء الخيارات الطويلة عادةً بشرطتَين (<span style="font-family:courier new,courier,monospace;">--</span>). سنستعمل هذا العرف في سكربتاتنا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_18">
<span class="pln">interactive=
filename=~/sysinfo_page.html

while [ "$1" != "" ]; do
    case $1 in
        -f | --file )           shift
                                filename=$1
                                ;;
        -i | --interactive )    interactive=1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done</span></pre>

<p>
	الشيفرة السابقة معقدة بعض الشيء، تحملني قليلًا ريثما أشرحها لك. 
</p>

<p>
	السطران الأولان سهلان، لم نضبط قيمةً للمتغير <span style="font-family:courier new,courier,monospace;">interactive</span>، مما يُشير إلى أنَّ المستخدم لم يطلب الوضع التفاعلي، ثم ضبطنا المتغير <span style="font-family:courier new,courier,monospace;">filename</span> إلى قيمة افتراضية، حيث سيُستخدَم هذا الاسم إن لم يُحدَّد اسمٌ آخر في سطر الأوامر. 
</p>

<p>
	أصبح لدينا الآن قيمٌ افتراضية في حال لم يضع المستخدم أيّة خيارات في سطر الأوامر. 
</p>

<p>
	أنشأنا بعد ذلك حلقة <span style="font-family:courier new,courier,monospace;">while</span> التي تمر على جميع عناصر سطر الأوامر وتتحقق من قيمها عبر كتلة <span style="font-family:courier new,courier,monospace;">case</span>، التي تكتشف وضع كل خيار من الخيارات الممكنة وتتعامل معه كما يجب. 
</p>

<p>
	الجزء المهم في السكربت السابق هو آلية عمل حلقة التكرار. تعتمد الحلقة السابقة على الأمر <span style="font-family:courier new,courier,monospace;">shift</span>. 
</p>

<p>
	الأمر <span style="font-family:courier new,courier,monospace;">shift</span> هو أمرٌ مضمَّن في الصَدَفة ويتعامل مع المعاملات الموضعية، حيث يؤدي إلى "إزاحة" أرقام جميع المعاملات وذلك بإنقاص 1 منها وذلك في كل مرة يُستدعى فيها. سيصبح ‎<span style="font-family:courier new,courier,monospace;">$2</span> -على سبيل المثال- ‎<span style="font-family:courier new,courier,monospace;">$1</span>، و ‎<span style="font-family:courier new,courier,monospace;">$3</span> سيصبح ‎<span style="font-family:courier new,courier,monospace;">$2</span>، و ‎ <span style="font-family:courier new,courier,monospace;">$4</span>سيصبح ‎<span style="font-family:courier new,courier,monospace;">$3</span>، وهكذا. جرِّب السكربت الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_20">
<span class="pln">#!/bin/bash

echo "You start with $# positional parameters"

# Loop until all parameters are used up
while [ "$1" != "" ]; do
    echo "Parameter 1 equals $1"
    echo "You now have $# positional parameters"

    # Shift all the parameters down by one
    shift

done</span></pre>

<h2>
	الحصول على وسيط أحد الخيارات
</h2>

<p>
	يتطلب الخيار <span style="font-family:courier new,courier,monospace;">‎-f</span> ذكر اسم الملف الذي ستُحفَظ فيه المخرجات بعده. يمكننا استخدام <span style="font-family:courier new,courier,monospace;">shift</span> مرةً أخرى للحصول على اسم العنصر التالي من وسائط سطر الأوامر وإسناد قيمته إلى المتغير <span style="font-family:courier new,courier,monospace;">filename</span>. سنتحقق لاحقًا من قيمة <span style="font-family:courier new,courier,monospace;">filename</span> للتأكد أنَّها تُمثِّل اسم ملف صحيح.
</p>

<h2>
	دمج مفسر خيارات سطر الأوامر مع السكربت
</h2>

<p>
	علينا الآن نقل بعض الأقسام من مكانها، وإضافة دالة لعرض طريقة استخدام الخيارات التي أضفناها أخيرًا إلى السكربت، وسنضيف اختبارًا للتأكد من صحة تفسير خيارات سطر الأوامر. سيبدو السكربت بعد التعديل كالآتي:
</p>

<pre class="ipsCode" id="ips_uid_2413_22">
#!/bin/bash

# sysinfo_page - A script to produce a system information HTML file

##### Constants

TITLE="System Information for $HOSTNAME"
RIGHT_NOW=$(date +"%x %r %Z")
TIME_STAMP="Updated on $RIGHT_NOW by $USER"

##### Functions

system_info()
{
    echo "&lt;h2&gt;System release info&lt;/h2&gt;"
    echo "&lt;p&gt;Function not yet implemented&lt;/p&gt;"

}   # end of system_info


show_uptime()
{
    echo "&lt;h2&gt;System uptime&lt;/h2&gt;"
    echo "&lt;pre&gt;"
    uptime
    echo "&lt;/pre&gt;"

}   # end of show_uptime


drive_space()
{
    echo "&lt;h2&gt;Filesystem space&lt;/h2&gt;"
    echo "&lt;pre&gt;"
    df
    echo "&lt;/pre&gt;"

}   # end of drive_space


home_space()
{
    # Only the superuser can get this information

    if [ "$(id -u)" = "0" ]; then
        echo "&lt;h2&gt;Home directory space by user&lt;/h2&gt;"
        echo "&lt;pre&gt;"
        echo "Bytes Directory"
        du -s /home/* | sort -nr
        echo "&lt;/pre&gt;"
    fi

}   # end of home_space


write_page()
{
    cat &lt;&lt;- _EOF_
    &lt;html&gt;
        &lt;head&gt;
        &lt;title&gt;$TITLE&lt;/title&gt;
        &lt;/head&gt;
        &lt;body&gt;
        &lt;h1&gt;$TITLE&lt;/h1&gt;
        &lt;p&gt;$TIME_STAMP&lt;/p&gt;
        $(system_info)
        $(show_uptime)
        $(drive_space)
        $(home_space)
        &lt;/body&gt;
    &lt;/html&gt;
_EOF_

}

usage()
{
    echo "usage: sysinfo_page [[[-f file ] [-i]] | [-h]]"
}


##### Main

interactive=
filename=~/sysinfo_page.html

while [ "$1" != "" ]; do
    case $1 in
        -f | --file )           shift
                                filename=$1
                                ;;
        -i | --interactive )    interactive=1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done


# Test code to verify command line processing

if [ "$interactive" = "1" ]; then
    echo "interactive is on"
else
    echo "interactive is off"
fi
echo "output file = $filename"


# Write page (comment out until testing is complete)

# write_page &gt; $filename</pre>

<h2>
	إضافة النمط التفاعلي
</h2>

<p>
	يمكن إضافة النمط التفاعلي بهذه الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_24">
<span class="pln">if [ "$interactive" = "1" ]; then

    response=

    echo -n "Enter name of output file [$filename] &gt; "
    read response
    if [ -n "$response" ]; then
        filename=$response
    fi

    if [ -f $filename ]; then
        echo -n "Output file exists. Overwrite? (y/n) &gt; "
        read response
        if [ "$response" != "y" ]; then
            echo "Exiting program."
            exit 1
        fi
    fi
fi</span></pre>

<p>
	تحققنا أولًا من أنَّ النمط التفاعلي مُفعَّل، وإلا فلا حاجة إلى فعل شيء. ثم سألنا المستخدم عن اسم الملف؛ لاحظ طريقة صياغة السؤال:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2413_26">
<span class="pln">echo -n "Enter name of output file [$filename] &gt; "</span></pre>

<p>
	سنعرض القيمة الحالية للمتغير <span style="font-family:courier new,courier,monospace;">filename</span>، لأنَّه لو ضغط المستخدم على زر <span style="font-family:courier new,courier,monospace;">Enter</span> دون كتابة أيّ شيء، فستُستخدم القيمة الافتراضية للمتغير <span style="font-family:courier new,courier,monospace;">filename</span>؛ ويتم ذلك عبر السطرين اللذان يليانه، حيث يتحققا من قيمة <span style="font-family:courier new,courier,monospace;">response</span>؛ فإن لم تكن قيمة <span style="font-family:courier new,courier,monospace;">response</span> فارغةً، فستُسنَد قيمة <span style="font-family:courier new,courier,monospace;">response</span> إلى المتغير <span style="font-family:courier new,courier,monospace;">filename</span>. وإلا فستُترَك قيمة <span style="font-family:courier new,courier,monospace;">filename</span> على حالها، محتفظةً بقيمتها الافتراضية. 
</p>

<p>
	بعد أن يُدخِل المستخدم اسم ملف الخرج، فسنتحقق من أنَّه موجود، فإن كان موجودًا، فسنسأل المستخدم إن كان يريد استبداله، وإن لم يكن جواب المستخدمy، فسينتهي تنفيذ البرنامج دون كتابة الملف. 
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://linuxcommand.org/lc3_wss0120.php" rel="external nofollow">Positional Parameters</a> لصاحبه William Shotts.
</p>
]]></description><guid isPermaLink="false">271</guid><pubDate>Fri, 10 Jun 2016 13:27:51 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x628;&#x646;&#x649; &#x627;&#x644;&#x62A;&#x62D;&#x643;&#x645; (Flow Control) &#x641;&#x64A; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts) -&#xA0;&#x627;&#x644;&#x62C;&#x632;&#x621; 2</title><link>https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-flow-control-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-%C2%A0%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-2-r268/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-case-while-until.png.8cd4475ff568e357cfe873f2d8b13fd5.png" /></p>

<p>
	<a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-flow-control-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-%C2%A0%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-1-r260/" rel="">تعلمنا في الجزء الأول من بُنى التحكم عن الأمر if</a> وكيف يُستخدم لتعديل مسار تنفيذ البرنامج بناءً على حالة خروج أحد الأوامر. يسمى هذا النوع من مسارات تنفيذ البرامج -وفق الاصطلاحات البرمجية- بالتفرّع (branching) لأنَّه يشبه كثيرًا التنقل في شجرة، فعندما تصل إلى تفرّع، فستُحدِّد نتيجة الشرط أيَّ فرعٍ ستذهب إليه. 
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17692" data-unique="vaygfp29g" src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-script-case-while-until.png.42da24190be4fb017f33bf5fac189920.png" alt="shell-script-case-while-until.png"></p>

<p>
	هنالك نوعٌ آخرٌ أكثر تعقيدًا من أنواع التفرع يُسمى <span style="font-family:courier new,courier,monospace;">case</span>، وهنالك عدِّة خيارات في <span style="font-family:courier new,courier,monospace;">case</span>، فعلى عكس التفرّع البسيط الذي فيه طريقان فقط، يمكن أن تكون هنالك عدِّة نواتج بناءً على تحقيق شرط معيّن لقيمةٍ ما. 
</p>

<p>
	يمكنك بناء مثل هذا النوع من أنواع التفرّع باستخدام عدِّة جمل <span style="font-family:courier new,courier,monospace;">if</span> شرطية. سنحاول في المثال الآتي التحقق من مدخلات المستخدم:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_9">
<span class="pln">#!/bin/bash

echo -n "Enter a number between 1 and 3 inclusive &gt; "
read character
if [ "$character" = "1" ]; then
    echo "You entered one."
elif [ "$character" = "2" ]; then
    echo "You entered two."
elif [ "$character" = "3" ]; then
    echo "You entered three."
else
    echo "You did not enter a number between 1 and 3."
fi</span></pre>

<p>
	لكن ما سبق ليس كفؤًا كما كنا نتوقع، ولكن لحسن الحظ، توفِّر الصَدَفة لنا حلًا أفضل لهذه المشكلة: الأمر المُضمَّن ‏<span style="font-family:courier new,courier,monospace;">case</span>، الذي يمكن استخدامه لبناء برنامج مكافئ تمامًا للبرنامج السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_11">
<span class="pln">#!/bin/bash

echo -n "Enter a number between 1 and 3 inclusive &gt; "
read character
case $character in
    1 ) echo "You entered one."
        ;;
    2 ) echo "You entered two."
        ;;
    3 ) echo "You entered three."
        ;;
    * ) echo "You did not enter a number between 1 and 3."
esac</span></pre>

<p>
	الشكل العام للأمر <span style="font-family:courier new,courier,monospace;">case</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_13">
<span class="pln">case word in
    patterns ) commands ;;
esac</span></pre>

<p>
	يُنفِّذ الأمر <span style="font-family:courier new,courier,monospace;">case</span> عباراتٍ برمجيةً معيّنة إذا طابَقت الكلمة نمطًا (pattern)، يمكنك وضع أي عدد من الأنماط والعبارات. ويمكن أن تكون الأنماط نصًا عاديًا أو "محارف بديلة" (wildcards). يمكن وضع أكثر من نمط في نفس السطر بفصل الأنماط بمحرف <span style="font-family:courier new,courier,monospace;">|</span>. هذا مثالٌ متقدمٌ يشرح لك ما أعنيه بكلامي السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_15">
<span class="pln">#!/bin/bash

echo -n "Type a digit or a letter &gt; "
read character
case $character in
                                # Check for letters
    [[:lower:]] | [[:upper:]] ) echo "You typed the letter $character"
                                ;;

                                # Check for digits
    [0-9] )                     echo "You typed the digit $character"
                                ;;

                                # Check for anything else
    * )                         echo "You did not type a letter or a digit"
esac</span></pre>

<p>
	لاحظ النمط الخاص <span style="font-family:courier new,courier,monospace;">*</span> الذي سيُطابِق أي شيء، لذلك سنحتاج إليه لمطابقة الحالات التي لم تُطابِقها الأنماط التي تسبقه. من المستحسن تضمين هذا النمط في نهاية الأمر <span style="font-family:courier new,courier,monospace;">case</span> لكي يُستخدَم لكشف المدخلات غير الصحيحة.
</p>

<h2>
	حلقات التكرار
</h2>

<p>
	آخر جزء من بُنى التحكم التي سنناقشها هي حلقات التكرار، تُنفِّذ حلقات التكرار قسمًا من البرنامج لعددٍ من المرات وذلك بناءً على حالة خروج أحد الأوامر. توفِّر الصَدَفة ثلاثة أوامر للتكرار: <span style="font-family:courier new,courier,monospace;">while</span> و <span style="font-family:courier new,courier,monospace;">until</span> و <span style="font-family:courier new,courier,monospace;">for</span>، وسنشرح <span style="font-family:courier new,courier,monospace;">while</span> و <span style="font-family:courier new,courier,monospace;">until</span> في هذا الدرس وسنترك <span style="font-family:courier new,courier,monospace;">for</span> لدرسٍ لاحق. 
</p>

<p>
	يؤدي الأمر <span style="font-family:courier new,courier,monospace;">while</span> إلى تنفيذ كتلة من الشيفرة مرارًا وتكرارًا لطالما كانت حالة خروج الأمر المُحدَّد <span style="font-family:courier new,courier,monospace;">true</span> (أي حالة الخروج 0). هذا مثالٌ بسيطٌ يعد الأرقام من 0 إلى 9:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_17">
<span class="pln">#!/bin/bash

number=0
while [ "$number" -lt 10 ]; do
    echo "Number = $number"
    number=$((number + 1))
done</span></pre>

<p>
	أنشأنا في السطر الثالث متغيرًا وأسميناه <span style="font-family:courier new,courier,monospace;">number</span> وأسندنا القيمة 0 إليه، ثم بدأنا حلقة <span style="font-family:courier new,courier,monospace;">while</span>. وكما لاحظت، كان الأمر التي ستختبر حلقة <span style="font-family:courier new,courier,monospace;">while</span> حالة خروجه هو الأمر <span style="font-family:courier new,courier,monospace;">test</span> الذي يختبر قيمة العدد <span style="font-family:courier new,courier,monospace;">number</span>. وفي مثالنا السابق، اختبرنا إذا كانت قيمة <span style="font-family:courier new,courier,monospace;">number</span> أصغر من 10. 
</p>

<p>
	لاحظ الكلمة <span style="font-family:courier new,courier,monospace;">do</span> في السطر الرابع والكلمة <span style="font-family:courier new,courier,monospace;">done</span> في السطر السابق. هاتان الكلمتان تحيطان بالشيفرة التي ستُكرَّر لطالما كانت حالة خروج الأمر المُحدَّد مساويةً للصفر. 
</p>

<p>
	في غالبية الحالات، تقوم الشيفرة التي ستُكرَّر بشيءٍ ما سيؤدي في نهاية المطاف إلى تغيير حالة خروج الأمر المُحدَّد، وإلا فستكون لديك حلقة تكرار لا نهائية؛ أي حلقةُ تكرارٍ لا يتوقف تنفيذها أبدًا. 
</p>

<p>
	تطبع الشيفرة التي ستُكرَّر في المثال السابق قيمة المتغير <span style="font-family:courier new,courier,monospace;">number</span> (الأمر <span style="font-family:courier new,courier,monospace;">echo</span> في السطر الخامس)، ثم تُزيد قيمة <span style="font-family:courier new,courier,monospace;">number</span> بمقدار 1 في السطر السادس. وفي كل مرة يكتمل فيها تنفيذ الشيفرة، فسيتم التحقق من قيمة حالة الخروج للأمر <span style="font-family:courier new,courier,monospace;">test</span>، وبعد التكرار العاشر للحلقة، فسيزداد المتغير <span style="font-family:courier new,courier,monospace;">number</span> عشر مرات وسينتهي الأمر <span style="font-family:courier new,courier,monospace;">test</span> بحالة خروج لا تساوي الصفر. وفي هذه المرحلة، سيُكمِل البرنامج مساره بتنفيذ التعليمات البرمجية التي تلي الكلمة <span style="font-family:courier new,courier,monospace;">done</span>، لكن ولمّا كانت <span style="font-family:courier new,courier,monospace;">done</span> هي آخر كلمة في مثالنا، فسينتهي تنفيذ البرنامج فورًا. 
</p>

<p>
	يعمل الأمر <span style="font-family:courier new,courier,monospace;">until</span> بشكلٍ مماثل، عدا أنَّ الشيفرة ستُكرَّر لطالما كانت حالة خروج الأمر المُحدَّد <span style="font-family:courier new,courier,monospace;">false</span> (أي ليست 0). لاحظ تغيير التعبير الذي مررناه للأمر <span style="font-family:courier new,courier,monospace;">test</span> لكي يعمل بشكلٍ مماثل للمثال السابق عن حلقة <span style="font-family:courier new,courier,monospace;">while</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_19">
<span class="pln">#!/bin/bash

number=0
until [ "$number" -ge 10 ]; do
    echo "Number = $number"
    number=$((number + 1))
done</span></pre>

<h2>
	بناء قائمة
</h2>

<p>
	طريقة شائعة لتوفير واجهة للمستخدم للبرامج النصيّة (أي التي تعمل من سطر الأوامر) هي استخدام القوائم. القائمة هي سلسلة من الخيارات التي يستطيع المستخدم انتقاء واحدة منها. 
</p>

<p>
	سنستخدم ما تعلمناه سابقًا عن الحلقات وعبارة <span style="font-family:courier new,courier,monospace;">case</span> لبناء برنامج بسيط فيه قائمة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_21">
<span class="pln">#!/bin/bash

selection=
until [ "$selection" = "0" ]; do
    echo "
    PROGRAM MENU
    1 - Display free disk space
    2 - Display free memory

    0 - exit program
"
    echo -n "Enter selection: "
    read selection
    echo ""
    case $selection in
        1 ) df ;;
        2 ) free ;;
        0 ) exit ;;
        * ) echo "Please enter 1, 2, or 0"
    esac
done</span></pre>

<p>
	الغرض من حلقة <span style="font-family:courier new,courier,monospace;">until</span> هو إعادة عرض القائمة في كل مرة يتم اختيار عنصر من القائمة فيها. ستتكرر الحلقة إلى أن يختار المستخدم 0 (خيار الخروج).
</p>

<p>
	لاحظ ماذا سنفعل إذا لم تكن مدخلات المستخدم صحيحة (1 أو 2 أو 0). 
</p>

<p>
	نستطيع إضافة دالة تطلب من المستخدم الضغط على الزر Enter بعد عرض كل خيار لتحسين طريقة عرض البرنامج عند تشغيله، وذلك بمسح الشاشة قبل إعادة عرض القائمة مرةً أخرى. هذا هو المثال المُحسَّن:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2813_23">
<span class="pln">#!/bin/bash

press_enter()
{
    echo -en "\nPress Enter to continue"
    read
    clear
}

selection=
until [ "$selection" = "0" ]; do
    echo "
    PROGRAM MENU
    1 - display free disk space
    2 - display free memory

    0 - exit program
"
    echo -n "Enter selection: "
    read selection
    echo ""
    case $selection in
        1 ) df ; press_enter ;;
        2 ) free ; press_enter ;;
        0 ) exit ;;
        * ) echo "Please enter 1, 2, or 0"; press_enter
    esac
done</span></pre>

<h2>
	عندما "يُعلِّق" حاسوبك … 
</h2>

<p>
	لقد مررنا جميعًا بتجربة "تعليق" أحد البرامج، الذي يحدث عندما يتوقف البرنامج عن العمل ولا يستجيب لأي شيء. ربما تظن أنَّ البرنامج قد توقف، إلا أنَّه -في معظم الحالات- ما يزال يعمل لكن واجهته مشكلةٌ في البنية المنطقية فيه وقد دخل في حلقة تكرار لا نهائية. 
</p>

<p>
	تخيل هذه الحالة: لنقل أنَّك وصلت جهازًا خارجيًا إلى حاسوبك، مثل قرص USB، لكنك نسيت تشغيله. ثم حاولت استخدام الجهاز لكن التطبيق علّق، فعندما يحدث ذلك، تستطيع أن تتخيل المحادثة الآتية بين التطبيق والمنفذ الذي يتصل عبره الجهاز:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			التطبيق: هل أنت جاهز؟ <br>
			المنفذ: الجهاز غير جاهز.
		</p>

		<p>
			التطبيق: هل أنت جاهز؟ <br>
			المنفذ: الجهاز غير جاهز.
		</p>

		<p>
			التطبيق: هل أنت جاهز؟ <br>
			المنفذ: الجهاز غير جاهز.
		</p>

		<p>
			التطبيق: هل أنت جاهز؟ <br>
			المنفذ: الجهاز غير جاهز. 
		</p>
	</div>
</blockquote>

<p>
	وسيستمر الأمر هكذا إلى ما لا نهاية … 
</p>

<p>
	البرامج المكتوبة بطريقة جيدة تتفادى الحالة السابقة بضبط مهلة زمنية (timeout)، وهذا يعني أنَّ حلقة التكرار تحسب عدد المحاولات أو تحسب مقدار الزمن الذي انتظرته لكي يحدث شيءٌ مُحدَّد. وإن تجاوز عدد المحاولات أو الزمن المُنتَظَر حدًّا معيّنًا، فسينتهي تنفيذ الحلقة وسيولِّد البرنامج رسالة خطأ. 
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://linuxcommand.org/lc3_wss0110.php" rel="external nofollow">Flow Control - Part 2</a> لصاحبه William Shotts.
</p>
]]></description><guid isPermaLink="false">268</guid><pubDate>Fri, 10 Jun 2016 12:26:33 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62D;&#x635;&#x648;&#x644; &#x639;&#x644;&#x649; &#x645;&#x62F;&#x62E;&#x644;&#x627;&#x62A; &#x645;&#x646; &#x644;&#x648;&#x62D;&#x629; &#x627;&#x644;&#x645;&#x641;&#x627;&#x62A;&#x64A;&#x62D; &#x648;&#x625;&#x62C;&#x631;&#x627;&#x621; &#x627;&#x644;&#x639;&#x645;&#x644;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x62D;&#x633;&#x627;&#x628;&#x64A;&#x629; &#x641;&#x64A; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts)</title><link>https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%AD%D8%B5%D9%88%D9%84-%D8%B9%D9%84%D9%89-%D9%85%D8%AF%D8%AE%D9%84%D8%A7%D8%AA-%D9%85%D9%86-%D9%84%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D9%81%D8%A7%D8%AA%D9%8A%D8%AD-%D9%88%D8%A5%D8%AC%D8%B1%D8%A7%D8%A1-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AD%D8%B3%D8%A7%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r266/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-scripts-keyboard-input.png.bf243c7b50e32a6021c2415d6f6d450e.png" /></p>

<p>
	لم تكن السكربتات التي نكتبها إلى الآن تفاعليةً، أي أنها لا تتطلب أيّ مدخلاتٍ من المستخدم. سنرى في هذا الدرس كيف نجعل السكربتات تسأل المستخدم أسئلةً وتحصل على الإجابة وتستخدمها.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17690" data-unique="xoe77o6fg" src="https://academy.hsoub.com/uploads/monthly_2016_06/shell-scripts-keyboard-input.png.c4eb718553d6e04a9749824a68f7510f.png" alt="shell-scripts-keyboard-input.png"></p>

<h2>
	read
</h2>

<p>
	استعمل الأمر <span style="font-family:courier new,courier,monospace;">read</span> للحصول على مدخلات من لوحة المفاتيح. يأخذ الأمر <span style="font-family:courier new,courier,monospace;">read</span> المدخلات من لوحة المفاتيح ويُسنِدها إلى متغير. هذا مثالٌ بسيطٌ عنه:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_7">
<span class="pln">#!/bin/bash

echo -n "Enter some text &gt; "
read text
echo "You entered: $text"</span></pre>

<p>
	عرضنا رسالةً في السطر الثالث، لاحظ كيف استعملنا الخيار<span style="font-family:courier new,courier,monospace;"> ‎-n</span> لكي نجعل الأمر <span style="font-family:courier new,courier,monospace;">echo</span> يُبقي على مؤشر الكتابة موجودًا في نفس السطر، أي أنَّه لن يطبع محرف الانتقال إلى سطرٍ جديد (كالعادة).  
</p>

<p>
	ثم استدعينا الأمر <span style="font-family:courier new,courier,monospace;">read</span> مع تمرير <span style="font-family:courier new,courier,monospace;">text</span> كوسيط، وما سيفعله هو انتظار المستخدم إلى أن يكتب شيئًا ثم يضغط على زر Enter، ثم سيُسنِد ما كتبه المستخدم إلى المتغير <span style="font-family:courier new,courier,monospace;">text</span>. 
</p>

<p>
	هذا مثالٌ جربنا فيه السكربت السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_13">
<span class="pln">$ read_demo.bash
Enter some text &gt; this is some text
You entered: this is some text</span></pre>

<p>
	إن لم تُحدِّد اسم المتغير الذي تريد أن يحفظ الأمر <span style="font-family:courier new,courier,monospace;">read</span> مدخلات المستخدم فيه، فسيَستعمِل متغير البيئة <span style="font-family:courier new,courier,monospace;">REPLY</span>. 
</p>

<p>
	هنالك عدِّة خيارات للأمر <span style="font-family:courier new,courier,monospace;">read</span>، أهم اثنين منها هما <span style="font-family:courier new,courier,monospace;">‎-t</span> و ‎<span style="font-family:courier new,courier,monospace;">-s</span>. يأتي الخيار ‎ <span style="font-family:courier new,courier,monospace;">-t</span>متبوعًا بعدد الثواني التي سينتظر فيها الأمرُ <span style="font-family:courier new,courier,monospace;">read</span> المستخدمَ لتوفير مدخلات. وهذا يعني أنَّ الأمر <span style="font-family:courier new,courier,monospace;">read</span> سيتوقف عن قبول مدخلات من المستخدم بعد هذه المهلة الزمنية. يمكن أن يُستخدَم هذا الخيار إذا كان على السكربت الاستمرار في التنفيذ حتى لو لم يوفِّر المستخدم مدخلات (ربما ستوضع قيمة افتراضية بدلًا من مدخلات المستخدم في هذه الحالة). هذا مثالٌ عن الخيار <span style="font-family:courier new,courier,monospace;">‎-t</span>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_11">
<span class="pln">#!/bin/bash

echo -n "Hurry up and type something! &gt; "
if read -t 3 response; then
    echo "Great, you made it in time!"
else
    echo "Sorry, you are too slow!"
fi</span></pre>

<p>
	يؤدي الخيار ‎<span style="font-family:courier new,courier,monospace;">-s</span> إلى عدم إظهار المدخلات التي يكتبها المستخدم على الشاشة، وهذا مفيدٌ عندما تسأل المستخدم عن كلمة مروره، أو غير ذلك من المعلومات السرية. 
</p>

<h2>
	العمليات الحسابية 
</h2>

<p>
	من البديهي أنَّ الحاسوب يستطيع إجراء عمليات حسابية بسيطة. توفِّر الصدفة إمكانية إجراء عمليات حسابية على الأعداد الصحيحة (integer). 
</p>

<p>
	ما هي الأعداد الصحيحة؟ هي الأعداد الكاملة مثل 1 و 2 و 456 و -235 التي لا تحتوي على فواصل عشرية مثل 0.5 و ‎.443 أو 3.1415. إذا كان من الضروري أن تتعامل مع الأعداد العشرية، فهنالك برنامجٌ منفصل اسمه <span style="font-family:courier new,courier,monospace;">bc</span> الذي تتعامل معه بلغة خاصة للحساب الدقيق، ويمكن أن يُستعمَل في سكربتات الصَدَفة لكنه خارج عن نطاق هذه السلسلة. 
</p>

<p>
	لنقل أنَّك تريد استخدام سطر الأوامر كآلة حاسبة بسيطة. تستطيع فعل ذلك كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_15">
<span class="pln">$ echo $((2+2))</span></pre>

<p>
	عندما تواجه الصَدَفة التعبير <span style="font-family:courier new,courier,monospace;">‎$(( ))‎</span> فستحاول وضع ناتج العملية الحسابية الموجودة داخل الأقواس بدلًا منه. لاحظ كيف سيتم تجاهل الفراغات:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_17">
<span class="pln">$ echo $((2+2))
4
$ echo $(( 2+2 ))
4
$ echo $(( 2 + 2 ))
4</span></pre>

<p>
	تستطيع الصَدَفة إجراء مختلف العمليات الحسابية الشهيرة (وغير الشهيرة). هذا مثالٌ عنها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_19">
<span class="pln">#!/bin/bash

first_num=0
second_num=0

echo -n "Enter the first number --&gt; "
read first_num
echo -n "Enter the second number -&gt; "
read second_num

echo "first number + second number = $((first_num + second_num))"
echo "first number - second number = $((first_num - second_num))"
echo "first number * second number = $((first_num * second_num))"
echo "first number / second number = $((first_num / second_num))"
echo "first number % second number = $((first_num % second_num))"
echo "first number raised to the"
echo "power of the second number   = $((first_num ** second_num))"</span></pre>

<p>
	لاحظ أنَّ علامة<span style="font-family:courier new,courier,monospace;"> $</span> التي تسبق أسماء المتغيرات غير ضرورية داخل التعابير الرياضية مثل <span style="font-family:courier new,courier,monospace;">first_num + second_num</span>. 
</p>

<p>
	جرِّب البرنامج الآتي وراقب كيف سيتعامل مع القسمة (تذكَّر أننا نقسِّم الأعداد الصحيحة هنا) وكيف سيتعامل مع الأعداد الكبيرة. عندما تصبح الأعداد كبيرةً جدًا، فسيحدث "فيضان" (overflow) في الذاكرة كما في عدَّاد المسافة المقطوعة في السيارات عندما يتجاوز عدد الكيلومترات التي صُمِّمَ لإحصائها. حيث يبدأ من جديد، لكن يجب المرور على الأعداد السالبة في الحاسوب (ﻷن هذه هي طريقة تخزين الأعداد داخليًا في الذاكرة). تؤدي القسمة على صفر (التي لا تجوز رياضيًا) إلى ظهور خطأ. 
</p>

<p>
	أنا متأكد أنَّك ستتعرف على أول أربع عمليات التي هي الجمع والطرح والضرب والقسمة، لكن العملية الخامسة غريبة بعض الشيء، الرمز <span style="font-family:courier new,courier,monospace;">%</span> يُمثِّل باقي القسمة (يُسمى modulo). تُجري هذه العملية القسمة لكن بدلًا من إظهار نتيجة القسمة، فستظهِر باقي القسمة. على الرغم من أنَّ ذلك لا يبدو مفيدًا جدًا، لكنه كذلك، حيث يوفِّر أداةً مفيدةً جدًا أثناء كتابة البرامج. على سبيل المثال، عندما يُعيد باقي القسمة القيمة صفر، فهذا يُشير إلى أنَّ العدد الأول هو من مضاعفات العدد الثاني، وقد تستفيد من هذه المعلومة كثيرًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_21">
<span class="pln">#!/bin/bash

number=0

echo -n "Enter a number &gt; "
read number

echo "Number is $number"
if [ $((number % 2)) -eq 0 ]; then
    echo "Number is even"
else
    echo "Number is odd"
fi</span></pre>

<p>
	وكذلك الأمر في برنامج يُحوِّل الثواني إلى ساعات ودقائق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3079_23">
<span class="pln">#!/bin/bash

seconds=0

echo -n "Enter number of seconds &gt; "
read seconds

hours=$((seconds / 3600))
seconds=$((seconds % 3600))
minutes=$((seconds / 60))
seconds=$((seconds % 60))

echo "$hours hour(s) $minutes minute(s) $seconds second(s)"</span></pre>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://linuxcommand.org/lc3_wss0100.php" rel="external nofollow">Keyboard Input And Arithmetic</a> لصاحبه William Shotts.
</p>
]]></description><guid isPermaLink="false">266</guid><pubDate>Fri, 10 Jun 2016 11:43:12 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x627;&#x644;&#x634;&#x627;&#x626;&#x639;&#x629; &#x627;&#x644;&#x62A;&#x64A; &#x62A;&#x62D;&#x62F;&#x62B; &#x639;&#x646;&#x62F; &#x643;&#x62A;&#x627;&#x628;&#x629; &#x633;&#x643;&#x631;&#x628;&#x62A;&#x627;&#x62A; &#x627;&#x644;&#x635;&#x62F;&#x641;&#x629; (Shell Scripts)</title><link>https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D8%A7%D9%84%D8%AA%D9%8A-%D8%AA%D8%AD%D8%AF%D8%AB-%D8%B9%D9%86%D8%AF-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%B3%D9%83%D8%B1%D8%A8%D8%AA%D8%A7%D8%AA-%D8%A7%D9%84%D8%B5%D8%AF%D9%81%D8%A9-shell-scripts-r262/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_05/shell-scripts-common-mistakes.png.6b40a1b303191617a8656aa1a5f7afe4.png" /></p>

<p>
	بعد أن ازدادت السكربتات التي نكتبها تعقيدًا، فأحببت أن أشير إلى بعض الأخطاء الشائعة التي قد تصادفك أثناء مسيرتك.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="17016" data-unique="7ecbjimvg" src="https://academy.hsoub.com/uploads/monthly_2016_05/shell-scripts-common-mistakes.png.749535bdefdca105a23bc94abf2c6c12.png" alt="shell-scripts-common-mistakes.png"></p>

<p>
	سنتعرض في هذا الدرس مثالًا ونعمل على تحليل الأخطاء التي قد نرتكبها، ولنسمِّ ذاك السكربت <span style="font-family:courier new,courier,monospace;">trouble.bash</span>، تأكد من كتابة السكربت كما هو موجود حرفيًا.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_8">
<span class="pln">#!/bin/bash

number=1

if [ $number = "1" ]; then
    echo "Number equals 1"
else
    echo "Number does not equal 1"
fi</span></pre>

<p>
	يجب أن يُخرِج السكربت السابق السطر "Number equals 1"، لأنَّ المتغير <span style="font-family:courier new,courier,monospace;">number</span> يساوي 1، إن لم تحصل على المخرجات التي توقعتها، فتحقق من صحة كتابتك للسكربت، فربما ارتكبتَ خطأً…
</p>

<h2>
	المتغيرات الفارغة
</h2>

<p>
	عدِّل السطر الثالث من السكربت من:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_10">
<span class="pln">number=1</span></pre>

<p>
	إلى:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_12">
<span class="pln">number=</span></pre>

<p>
	ثم شغِّل السكربت مرةً أخرى، وستحصل هذه المرة على المخرجات الآتية:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_14">
<span class="pln">$ ./trouble.bash
/trouble.bash: [: =: unary operator expected.
Number does not equal 1</span></pre>

<p>
	كما لاحظت، عَرَضَت الصَدَفة bash رسالة خطأ عندما شغلنا السكربت، وربما ظننتَ أنَّ حذف القيمة "1" من السطر الثالث قد أدى إلى خطأٍ بنيوي (syntax error) لكن هذا ليس صحيحًا، ألقِ نظرةً إلى رسالة الخطأ مجددًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_16">
<span class="pln">./trouble.bash: [: =: unary operator expected</span></pre>

<p>
	يمكننا ملاحظة أنَّ ‎<span style="font-family:courier new,courier,monospace;">./trouble.bash</span> يُبلِّغ عن الخطأ، الذي يرتبط -بشكلٍ أو بآخر- مع <span style="font-family:courier new,courier,monospace;">]</span>؛ تذكَّر أنَّ<span style="font-family:courier new,courier,monospace;"> ] </span>هو اختصارٌ للأمر المُضمَّن في الصَدَفة <span style="font-family:courier new,courier,monospace;">test</span>. ومن رسالة الخطأ السابقة استطعنا تحديد أنَّ الخطأ يحدث في السطر الخامس وليس الثالث. 
</p>

<p>
	عليّ القول بادئ الأمر أنَّه لا توجد أيّة مشكلة في السطر الثالث، حيث<span style="font-family:courier new,courier,monospace;"> number=‎ </span>صحيحة بنيويًا؛ فقد ترغب في بعض الأحيان بحذف القيمة المُخزَّنة في متغيّر. يمكنك التحقق من سلامة هذه الصياغة بكتابتها وتجربتها في سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_27">
<span class="pln">$ number=
$</span></pre>

<p>
	أرأيت! لا توجد رسالة خطأ، لكن ما هو الشيء الخاطئ في السطر الخامس؟ لقد جربناه قبل تعديل السكربت ولم يكن يسبب أيّة مشاكل. 
</p>

<p>
	لكي نفهم هذا الخطأ، علينا أن ننظر إلى الموضوع من وجهة نظر الصَدَفة. وَضَعَت الصَدَفة، في السطر الخامس، قيمة المتغير <span style="font-family:courier new,courier,monospace;">number</span> عندما رأت ‎<span style="font-family:courier new,courier,monospace;">$number</span>. ففي أول محاولة لتشغيل السكربت (أي عندما كان <span style="font-family:courier new,courier,monospace;">number=1</span>)، بدَّلَت الصدفة المتغير ‎<span style="font-family:courier new,courier,monospace;">$number</span> بالرقم 1 كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_29">
<span class="pln">if [ 1 = "1" ]; then</span></pre>

<p>
	لكننا عندما أزلنا قيمة المتغير (<span style="font-family:courier new,courier,monospace;">number=</span>‎)، فستحاول الصدفة تنفيذ ما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_31">
<span class="pln">if [ = "1" ]; then</span></pre>

<p>
	وهذا خطأ، ويُفسِّر أيضًا ما تبقى من رسالة الخطأ التي حصلنا عليها. المُعامِل = هو معامِل ثنائي، الذي يعني أنَّه يتوقع وجود عنصرين (كل عنصر على طرف). وما تحاول الصَدَفة إخبارنا به هو أنَّ هنالك عنصرٌ واحدٌ فقط، ولهذا يجب وضع معامل أحادي (مثل !) الذي يتطلب وجود عنصر وحيد فقط. <br>
	علينا تعديل السطر الخامس إلى ما يلي لحل هذه المشكلة:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_33">
<span class="pln">if [ "$number" = "1" ]; then</span></pre>

<p>
	وسترى الصَدَفة ما يلي (إذا كانت قيمة<span style="font-family:courier new,courier,monospace;"> number=‎</span>):
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_35">
<span class="pln">if [ "" = "1" ]; then</span></pre>

<p>
	وبهذا تجنبنا هذا الخطأ. 
</p>

<p>
	تعلمنا من هذا الخطأ أمرًا مهمًا عند كتابة السكربتات: خذ بعين الاعتبار ماذا سيحدث لو كانت قيمة أحد المتغيرات فارغة.
</p>

<h2>
	غياب إحدى علامات الاقتباس
</h2>

<p>
	عدِّل السطر السادس وأزل علامة إغلاق الاقتباس من نهاية السطر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_37">
<span class="pln">echo "Number equals 1</span></pre>

<p>
	ثم شغِّل السكربت مرةً أخرى وستحصل على:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_39">
<span class="pln">$ ./trouble.bash
./trouble.bash: line 8: unexpected EOF while looking for matching "
./trouble.bash: line 10 syntax error: unexpected end of file</span></pre>

<p>
	هذه مشكلةٌ أخرى شائعةٌ تُسبِّب مشاكل في أماكن أخرى في السكربت. ماذا يحدث لو استمرت الصَدَفة بحثها عن علامة إغلاق الاقتباس لمعرفة نهاية سلسلةٍ نصيةٍ ما، لكنها وصلت إلى نهاية الملف ولم تجدها. 
</p>

<p>
	يصعب كثيرًا اكتشاف هذا النوع من الأخطاء في السكربتات الطويلة؛ وهذا أحد الأسباب التي تدفعك لتجربة السكربتات بين الحين والآخر عندما تكتبها لوجود كمية قليلة من الشيفرات الجديدة التي عليك اختبارها. أرى أيضًا أنَّ استخدام المحررات النصيّة التي توفِّر تلوينًا للشيفرات يساعد كثيرًا في الكشف عن مثل هذه الأخطاء.
</p>

<h2>
	عزل مكان المشكلة
</h2>

<p>
	قد تكون عملية إيجاد الأخطاء والعِلل في برنامجك صعبة ومحبطة، هذه بعض التقنيات التي قد تستفيد منها: 
</p>

<p>
	اعزل أجزاءً من الشيفرات بوضع علامة تعليق قبل الأسطر التي لا تريد أن تنفذها الصَدَفة. طبِّق هذا على كتلة من الشيفرات لكي ترى إن اختفت مشكلة معيّنة. وبهذه الآلية ستعرف ما هو الجزء الذي يسبب (أو لا يسبب) المشكلة. 
</p>

<p>
	على سبيل المثال، لو عدنا إلى السكربت الذي فيه علامة اقتباس ناقصة، فيمكننا أن نعزل المشكلة كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_25">
<span class="pln">#!/bin/bash

number=1

if [ $number = "1" ]; then
    echo "Number equals 1
#else
#   echo "Number does not equal 1"
fi</span></pre>

<p>
	سنعلم بعد وضع عبارة <span style="font-family:courier new,courier,monospace;">else</span> في تعليق ثم تشغيل السكربت أنَّ المشكلة ليس في عبارة <span style="font-family:courier new,courier,monospace;">else</span> حتى لو أشارت رسالة الخطأ إلى ذلك. 
</p>

<p>
	استخدم الأمر <span style="font-family:courier new,courier,monospace;">echo</span> للتحقق من القيم. فبعد أن تكتسب خبرة في تتبع العلل، ستكتشف أنَّ العلل ستتواجد في مكانٍ مختلف عن المكان الذي تتوقع وجودها فيه. إحدى المشاكل الشائعة هي افتراضك أنَّ التسلسل المنطقي لبرنامجك صحيحٌ تمامًا، وعندما ترى مشكلة في مرحلة ما في البرنامج فستفترض أنَّها موجودة هناك؛ وهذا خاطئ في معظم الحالات. يمكنك وضع أوامر <span style="font-family:courier new,courier,monospace;">echo</span> في الشيفرة أثناء محاولة تنقيح (debugging) الأخطاء لكي تحصل على رسائل تؤكد لك أنَّ البرنامج يعمل كما تتوقع. 
</p>

<p>
	هنالك نوعان من الرسائل التي عليك وضعها. الغرض من أول نوع هو الإعلان أنَّ التنفيذ قد وصل إلى مكان معيّن في البرنامج، ولقد رأينا ذلك سابقًا عند كتابتنا لشيفرات وهمية في الدوال التي أضفناها. وهذا مفيد لكي تعلم أنَّ مسار تنفيذ البرنامج مماثل تمامًا لما نتوقعه. 
</p>

<p>
	النوع الثاني يعرض قيم المتغيرات المستخدمة في الحسابات أو الاختبارات. قد تجد في بعض الأحيان قسمًا من السكربت لا يُنفَّذ تنفيذًا سليمًا لأنك افترضت أنَّ شيئًا ما في ما سبقه من الشيفرات صحيحٌ؛ إلا أنَّ فيه مشكلةً تؤدي إلى فشل تنفيذ ما يليه من الشيفرات.
</p>

<h2>
	مراقبة تشغيل السكربت
</h2>

<p>
	من الممكن أنَّ تعرض لك bash ما الذي يحدث عندما تُشغِّل السكربت. وذلك بإضافة الخيار ‎-x في أول سطر من السكربت كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_22">
<span class="pln">#!/bin/bash -x</span></pre>

<p>
	وعندما ستُشغِّل السكربت، فستعرض bash كل سطر ستحاول تنفيذه (بعد تعويض قيم المتغيرات…). تُسمى هذه التقنية بالتتبع (tracing)، وهذا مثالٌ عنها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_20">
<span class="pln">$ ./trouble.bash
+ number=1
+ '[' 1 = 1 ']'
+ echo 'Number equals 1'
Number equals 1</span></pre>

<p>
	تستطيع أيضًا أن تستعمل الأمر <span style="font-family:courier new,courier,monospace;">set</span> داخل السكربت لتفعيل أو تعطيل التتبع. استخدم <span style="font-family:courier new,courier,monospace;">set -x </span>لتشغيل التتبع و<span style="font-family:courier new,courier,monospace;"> set +x</span> لتعطيل التتبع، مثال:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1617_18">
<span class="pln">#!/bin/bash

number=1

set -x
if [ $number = "1" ]; then
    echo "Number equals 1"
else
    echo "Number does not equal 1"
fi
set +x</span></pre>

<p>
	ترجمة -وبتصرّف- للمقال <a href="http://linuxcommand.org/lc3_wss0090.php" rel="external nofollow">Stay Out Of Trouble</a> لصاحبه William Shotts.
</p>
]]></description><guid isPermaLink="false">262</guid><pubDate>Tue, 31 May 2016 05:25:30 +0000</pubDate></item></channel></rss>
