شرح أداة tee لحفظ مخرجات الطرفية على الملفات

دليل استخدام أداة سطر الأوامر tee

مقدمة

خلال عمل المستخدم على الطرفية باستخدام سطر الأوامر؛ قد يحتاج أحيانا لنسخ المخرجات لاستخدامها لاحقا أو مشاركتها مع الآخرين لطلب المساعدة. من الأدوات التي تسهل العملية السابقة أداة ‘tee‘. سنتعرف في هذا الدليل على كيفية استخدام هذا الأمر مع أمثلة مبسطة.

ما أداة tee؟

أداة سطر أوامر على أنظمة جنو/لينكس، يتمثل عملها في حفظ أو كتابة مخرجات أمر معين (منفذٍّ على الطرفية) في مِلَفّ أو عدة ملفات (حسب حاجة المستخدم) لاستخدامه لاحقا لأغراض مختلفة.

طريقة استخدام الأمر tee

الصيغة

tee [OPTION] [FILE]

أمثلة على استخدام الأداة

1. كتابة المخرجات على مِلَفّ واحد

أبسط عمل للأمر tee هو كتابة المخرجات دون أي خيارات في مِلَفّ واحد.

الصيغة

command | tee filename

ملاحظة: في سطر الأوامر يستخدم زر | أو كما يسمى بالإنجليزية ‘pipe’ أو ‘vertical bar’ لإعادة توجيه مخرجات أمر معين وتحويلها لمدخلات أمر آخر.

مثال

في هذا المثال سنستخدم الأمر ls لعرض محتوى مجلد معين بطريقة سهلة القراءة ومرتبة من الأكبر إلى الأصغر حسب الحجم. ثم نستخدم الأمر tee لحفظ مخرجات الأمر ls السابق في مِلَفّ نصي.

ls -shS | tee list_of_files.txt
[linuxaw@linuxaw Ubuntu Flavors]$ ls -shS | tee list_of_files.txt
total 24G
4.1G ubuntustudio-21.10-dvd-amd64.iso
3.6G ubuntukylin-21.10-desktop-amd64.iso
3.2G ubuntu-mate-21.10-desktop-amd64.iso
3.2G kubuntu-21.10-desktop-amd64.iso
3.0G ubuntu-budgie-21.10-desktop-amd64.iso
3.0G ubuntu-21.10-desktop-amd64.iso
2.0G xubuntu-21.10-desktop-amd64.iso
2.0G lubuntu-21.10-desktop-amd64.iso

نستطيع الآن تصفح محتوى المِلَفّ عبر محرر النصوص أو مباشرة باستخدام الأمر cat في نفس جلسة الطرفية.

cat list_of_files.txt
[linuxaw@linuxaw Ubuntu Flavors]$ cat list_of_files.txt
total 24G
4.1G ubuntustudio-21.10-dvd-amd64.iso
3.6G ubuntukylin-21.10-desktop-amd64.iso
3.2G ubuntu-mate-21.10-desktop-amd64.iso
3.2G kubuntu-21.10-desktop-amd64.iso
3.0G ubuntu-budgie-21.10-desktop-amd64.iso
3.0G ubuntu-21.10-desktop-amd64.iso
2.0G xubuntu-21.10-desktop-amd64.iso
2.0G lubuntu-21.10-desktop-amd64.iso

2. كتابة المخرجات على أكثر من مِلَفّ

يمكن استخدام الأمر tee لحفظ المخرجات على عدة ملفات مختلفة بنفس المحتوى كنسخ احتياطية مثلا. يتم ذلك بكتابة أسماء الملفات متتالية والفصل بينها بمسافة (زر Space).

الصيغة

command | tee file_name_1 file_name_2 file_name_3

مثال

سنستخدم في هذا المثال الأمر df لعرض استهلاك مساحة قسم المنزل.

df -h /home | tee home_usage_1.txt home_usage_2.txt home_usage_3.txt
[linuxaw@linuxaw ~]$ df -h /home | tee home_usage_1.txt home_usage_2.txt home_usage_3.txt
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda11       45G   20G   23G  47% /home

هذه مخرجات عرض الملفات الثلاثة المنشأة

cat home_usage_1.txt home_usage_2.txt home_usage_3.txt
[linuxaw@linuxaw ~]$ cat home_usage_1.txt home_usage_2.txt home_usage_3.txt
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda11       45G   20G   23G  47% /home
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda11       45G   20G   23G  47% /home
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda11       45G   20G   23G  47% /home

3. كتابة المخرجات في نهاية المِلَفّ

عند كتابة اسم المِلَفّ بعد الأمر tee مباشرة دون خيارات (options) كما في الأمثلة السابقة فإن الأداة تستبدل محتوى المِلَفّ إن كان موجودا. لإضافة المخرجات لنهاية المِلَفّ دون استبداله نستخدم خِيار a- بعد الأمر tee.

الصيغة

command | tee -a filename
command | tee --append filename

مثال

سنفرض في مثالنا هذا أننا سنستخدم الأمر free لعرض استهلاك الذاكرة العشوائية كل مدة زمنية نحددها بأنفسنا من أجل المقارنة، لذلك ننفذ الأمر

free -h | tee memory_usage.txt
[linuxaw@linuxaw ~]$ free -h | tee memory_usage.txt
              total        used        free      shared  buff/cache   available
Mem:          7.3Gi       1.1Gi       3.2Gi       155Mi       2.9Gi       5.7Gi
Swap:         8.4Gi       6.0Mi       8.4Gi

بعد مدة معينة من الاستخدام نعيد تنفيذ الأمر لكن هذه المرة مع خِيار a- للاحتفاظ بالمخرجات الأولى من أجل المقارنة.

free -h | tee -a memory_usage.txt
[linuxaw@linuxaw ~]$ free -h | tee -a memory_usage.txt
              total        used        free      shared  buff/cache   available
Mem:          7.3Gi       1.6Gi       2.6Gi       244Mi       3.0Gi       5.1Gi
Swap:         8.4Gi       6.0Mi       8.4Gi

عند عرض محتوى المِلَفّ المنشأ تكون النتيجة كالآتي

cat memory_usage.txt
[linuxaw@linuxaw ~]$ cat memory_usage.txt 
              total        used        free      shared  buff/cache   available
Mem:          7.3Gi       1.1Gi       3.2Gi       155Mi       2.9Gi       5.7Gi
Swap:         8.4Gi       6.0Mi       8.4Gi
              total        used        free      shared  buff/cache   available
Mem:          7.3Gi       1.6Gi       2.6Gi       244Mi       3.0Gi       5.1Gi
Swap:         8.4Gi       6.0Mi       8.4Gi

4. كتابة المخرجات مع إخفاء ظهورها

يمكن للمستخدم كتابة مخرجات أمر معين على مِلَفّ دون إظهار هذه المخرجات في شاشة الطرفية. يتم ذلك باستخدام dev/null/ بعد الأمر tee.

الصيغة

command | tee filename > /dev/null

مثال

سنستخدم في هذا المثال الأمر uname لعرض المعلومات عن نظام التشغيل.

uname -a | tee system_info.txt > /dev/null
[linuxaw@linuxaw ~]$ uname -a | tee system_info.txt > /dev/null
[linuxaw@linuxaw ~]$ 

نلاحظ في المثال الماضي أنه لا تظهر أي مخرجات على شاشة الطرفية. للتحقق من مخرجات الأمر المكتوبة في المِلَفّ نستخدم الأداة cat.

cat system_info.txt
[linuxaw@linuxaw ~]$ cat system_info.txt 
Linux linuxaw 5.13.8-pclos1 #1 SMP Wed Aug 4 12:43:06 CDT 2021 x86_64 x86_64 x86_64 GNU/Linux

5. كتابة المخرجات مع تجاهل المقاطعة

عند استخدام خِيار i- مع الأمر tee فإن ذلك يُمَكِّن الأداة من تجاهل المقاطعة التي تحدث للعملية أو التي يجريها المستخدم بالضغط على اختصار Ctrl+C في لوحة المفاتيح. وبذلك يخرج الأمر tee بشكل آمن بعد كتابة المخرجات بشكل صحيح.

الصيغة

command | tee -i filename
command | tee --ignore-interrupts filename

مثال

نستخدم هنا الأداة ping التي تفحص اتصال الجهاز بجهاز آخر وتظهر نتائج الفحص. سنفحص الاتصال مع خادم محرك البحث Searx. ولمعرفة الفرق ننفذ الأمر أولا دون استخدام خِيار تجاهل المقاطعة. ثم نضغط على Ctrl+C خلال العملية لمقاطعتها.

ping searx.me | tee ping_stats.txt
[linuxaw@linuxaw ~]$ ping searx.me | tee ping_stats.txt
PING searx.me (194.150.168.104) 56(84) bytes of data.
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=1 ttl=49 time=62.7 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=2 ttl=49 time=53.2 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=3 ttl=49 time=53.8 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=4 ttl=49 time=63.7 ms
^C
[linuxaw@linuxaw ~]$ 

نعرض الآن مخرجات الملف

cat ping_stats.txt
[linuxaw@linuxaw ~]$ cat ping_stats.txt 
PING searx.me (194.150.168.104) 56(84) bytes of data.
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=1 ttl=49 time=62.7 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=2 ttl=49 time=53.2 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=3 ttl=49 time=53.8 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=4 ttl=49 time=63.7 ms

نعيد الكرة لكن مع استخدام خِيار تجاهل المقاطعة

ping searx.me | tee -i ping_stats.txt
[linuxaw@linuxaw ~]$ ping searx.me | tee -i ping_stats.txt
PING searx.me (194.150.168.104) 56(84) bytes of data.
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=1 ttl=49 time=55.0 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=2 ttl=49 time=62.3 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=3 ttl=49 time=63.6 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=4 ttl=49 time=59.1 ms
^C
--- searx.me ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 55.000/60.035/63.656/3.344 ms
[linuxaw@linuxaw ~]$ 

نعيد عرض مخرجات الملف

cat ping_stats.txt
[linuxaw@linuxaw ~]$ cat ping_stats.txt 
PING searx.me (194.150.168.104) 56(84) bytes of data.
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=1 ttl=49 time=55.0 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=2 ttl=49 time=62.3 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=3 ttl=49 time=63.6 ms
64 bytes from 104.168.150.194.in-addr.arpa (194.150.168.104): icmp_req=4 ttl=49 time=59.1 ms

--- searx.me ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 55.000/60.035/63.656/3.344 ms

نلاحظ أن الفرق بين النتيجتين أن عدم استخدام خِيار i- يؤدي لعدم حفظ ملخص الإحصائيات آخر المخرجات وهو ما حصلنا عليه في المثال الثاني بعد استخدام الخِيار.

6. توجيه مخرجات أمر معين نحو أمر آخر

يمكن استخدام علامة ‘pipe‘ لجعل المخرجات التي يكتبها الأمر tee مدخلات لأمر آخر يُنَفَّذُ بعده.

الصيغة

command_1 | tee -i filename | command_2

مثال

نستخدم هنا الأمر ls لعرض محتويات مجلد معين ثم نستخدم الأمر grep للبحث عن كلمة معينة في أسماء الملفات الموجودة

ls | tee list_of_files.txt | grep "xubuntu"
[linuxaw@linuxaw Ubuntu Flavors]$ ls | tee list_of_files.txt | grep "xubuntu"
xubuntu-21.10-desktop-amd64.iso

7. اِستخدام الأمر tee مع أداة sudo

يحتاج التعديل على ملفات النظام إلى الصلاحيات الإدارية. يستعمل المستخدمون لهذه المهام محررات النصوص من الطرفية أو بواسطة الواجهة الرسومية. يمكن أيضا استخدام الأمر tee مع الأمر sudo للكتابة على مِلَفّ يتطلب هذه الصلاحيات.

الصيغة

عند الكتابة على الملف

text | sudo tee filename

عند الإضافة لنهاية الملف

text | sudo tee -a filename

مثال

سنفرض أننا نريد تغيير اسم المضيف (hostname) في مِلَفّ hostname الموجود في مسار etc. نستخدم الأمر echo لطباعة الاسم الجديد ثم نستخدم tee لكتابته في المِلَفّ المذكور.

echo "linuxaw-host" | sudo tee /etc/hostname
[linuxaw@linuxaw ~]$ echo "linuxaw-host" | sudo tee /etc/hostname
[sudo] password for linuxaw: 
linuxaw-host

بتنفيذنا للأمر السابق يستبدل tee المِلَفّ القديم (اِسم المضيف القديم) ويعوضه بالملف الجديد (اِسم المضيف الجديد).

cat /etc/hostname
[linuxaw@linuxaw ~]$ cat /etc/hostname
linuxaw-host

الحصول على المساعدة لاستخدام tee

يمكن الوصول لدليل استخدام الأداة والحصول على المساعدة بواسطة الأمرين اﻵتيين

tee --help
man tee

خاتمة

بقراءتك لهذا الدليل تكون قد تعرفت إلى كيفية استخدام الأداة tee بشكل أساسي. ومن المحتمل أنك أدركت أيضا أهميتها وفائدتها في حفظ المخرجات لاستخدامها لاحقا. يمكنك مطالعة تصنيف أوامر الطرفية لدروس أكثر حول استخدام سطر الأوامر على أنظمة جنو/لينكس.

مسرور
مسرور
3
حزين
حزين
0
متحمس
متحمس
2
نعسان
نعسان
0
غاضب
غاضب
0
متفاجئ
متفاجئ
0
معاذ جِيجلي
معاذ جِيجلي
المقالات: 73