ساخت و پیکربندی سرویس bayand برای لینوکس (2)

چهارشنبه, ۱ شهریور ۱۴۰۲، ۰۹:۵۷ ب.ظ

سلام 

در قسمت قبلی اومدیم اسکریپت اصلی کار رو نوشتیم که میرفت وبلاگ های بروزشده رو بدست میاورد . این قسمت میخوایم ببینیم چطور میشه اسکریپت رو به عنوان یک سرویس در لینوکسمون پیکربندیش کنیم که دائما در پس زمینه به طور خودکار اجرا بشه و کارشو انجام بده .

خب بحث سرویس هارو داریم توی لینوکس . اصلا سرویس چیه ؟ 

در پایین ترین سطح تعریف ، سرویس هم مثل یک برنامه عادی داره توسط سیستم عامل اجرا میشه اما خب تفاوت سرویس با برنامه عادی چیه ؟

برنامه های عادی معمولا مستقیما توسط کاربر کنترل میشن و خدمتی رو مستقیما به کاربر ارائه میدن اما سرویس ها برنامه هایی هستند که توسط خود سیستم عامل مدیریت میشن و خدماتی رو برای کاربر و به طور غیر مستقیم به ارمغان میاره . این غیر مستقیم که میگم اینجوریه که سرویس ها خدماتی رو در اختیار برنامه های عادی قرار میدن و برنامه های عادی از اون سرویس ها در سیستم عامل استفاده میکنن تا خدماتی رو به کاربر ارائه بدن . 

فرضا در لینوکس ما سرویسی به نام CUPS داریم که مخفف Common Unix Printing System هستش . این سرویس برای کارهای مربوط به پرینت کردن با استفاده از دستگاه های پرینتر به کار میره . واقعیت اینه که سرویس CUPS میتونه پرینتر ها رو درک کنه و باهاشون ارتباط بگیره . حالا یه برنامه عادی توی سیستم عاملمون مثلا PDF Reader اگه بخواد یک فایلی رو پرینت کنه خب خودش که نمیتونه مستقیما به پرینتر وصل بشه و به پرینتر بگه این اطلاعاتو برای من چاپ کن ! کلی دنگ و فنگ داره . اینجا از خدماتی که سرویس CUPS ارائه میده استفاده میکنه تا اطلاعاتشو پرینت کنه . دیدید ! برنامه PDF Reader از سرویس CUPS کمک گرفت تا اطلاعاتشو برای کاربر چاپ کنه . اینجوریه که CUPS به طور غیر مستقیم یه خدمتی رو به کاربر ارائه داده . 

این مفهوم سرویس توی همه ی سیستم عامل هاست نه فقط لینوکس . 

حالا ما یه چیز دیگه ای هم داریم به اسم برنامه های Daemon . اینا دیگه چی هستن ؟‌ ما به برنامه ها یا پروسه هایی که در پس زمینه اجرا میشن و مستقیما توسط کاربر کنترل نمیشن میگیم Daemon . سرویس ها معمولا Daemon هستند چون مستقیما با کاربر ارتباطی ندارن طبق توضیحاتی که بالا دادیم ولی ما داریم سرویس هایی هم که بخش هایی دارن که مستقیما با کاربر در ارتباطه بنابراین نمیتونیم بگیم لزوما همه ی سرویس ها Daemon هستند . 

به خاطر همینه آخر اسم سرویس ها تو لینوکس بعضا یه d وجود داره این d مخفف daemon هستش :)

 

خب تا اینجا میدونیم سرویس چیه . اشاره کردیم که سرویس ها توسط سیستم عامل مدیریت میشن . این مدیریت شدنه چجوری انجام میشه ؟‌

بد نیست پروسه بوت شدن سیستم های لینوکسی رو به طور خلاصه بررسی کنیم . از اون لحظه ای که شما دکمه پاور سیستمتون رو میزنید این اتفاقات میفته و پروسه زیر به ترتیب طی میشه تا سیستم لینوکسیتون بالا بیاد :

 

۱ - Firmware : به محض زدن دکمه پاور تقریبا اولین کدی که توی سیستم شما اجرا میشه سفت افزاری (firmware) هست که روی مادربردتون قرار گرفته . این سفت افزار داخل یک حافظه فقط خواندنی (ROM) روی سخت افزار سیستمتون نوشته شده . وظیفه ی این سفت افزار این هست که یک سری تست ها انجام بده ببینه سخت افزار شما آماده ی اجرای سیستم عامل هست یا نه و نهایتا کثیف کاری های اول کار رو انجام بده و همه چیو آماده کنه تا سیستم عامل بتونه نهایتا روی سیستم شما بالا بیاد . این سفت افزار در سیستم های قدیمی تر BIOS هستش و در سیستم های جدید تر UEFI  .

(اگه دیده باشید سیستمای قدیمی رو وقتی روشنش میکردیم چند ثانیه بعد یه بوق میزد . این بوق بایوسه . یکی از کارایی که سفت افزار bios انجام میده اینه که چک میکنه سخت افزار شما اوکیه . اگر مشکلی با سخت افزار نبود و سیستمتون میتونست به درستی کارکنه یه بوق میزد یعنی حله سید بریم !‌ )

 

۲ - Boot Loader :  وقتی سفت افزار وظایف خودش رو انجام داد یک برنامه ای از روی هارد شما اجرا میکنه به اسم boot loader . کار این بوت لودر این هستش که سیستم عامل شما رو بارگذاری و اجرا کنه . اگر چندین سیستم عامل روی سیستمتون داشته باشید بوت لودر یک منو در اختیارتون قرار میده که انتخاب کنید میخواید وارد کدوم سیستم عاملاتون بشید . این بوت لودر معمولا به عنوان بخشی از خود سیستم عاملتون روی هاردتون نصب میشه و یکی از معروف ترین و پراستفاده ترین بوت لودر های موجود برای سیستم های لینوکسی grub هستش .

 

۳ - Kernel : وقتی شما داخل بوت لودر انتخاب کردید کدوم سیستم عاملتون میخواید اجرا بشه ، بوت لودر میره هسته سیستم عامل انتخابی که بهش میگن Kernel اون سیستم عامل رو در حافظه بارگذاری و اجرا میکنه .

 

۴ - init : اولین پروسه ای هست که به طور خودکار توسط kernel (هسته سیستم عامل) اجرا میشه . این پروسه همیشه pid برابر ۱ خواهد داشت . این پروسه وظیفه داره تا تمام باقی پروسه هایی که کاربر و سیستم نیاز دارن رو اجرا کنه . یکی از کارای مهمی که این پروسه انجام میده همون بحث مدیریت سرویسه . میاد میبینه با توجه به وضعیت فعلی سیستم عامل کدوم سرویس هارو باید خودکار اجرا کنه و کدومارو نه . به طور تاریخی ما همیشه به این پروسه میگیم init چون قبلا اسم این پروسه واقعا init بوده ولی الان توی لینوکسای مدرن systemd جاشو گرفته . ولی هنوزم بهش میگیم init تا چشم systemd کور شه :)

 

اینارو گفتم که بدونید نهایتا سروکار با این systemd هستش چون این هست که مدیریت میکنه حین بوت سیستم کدوم سرویس ها باید اجرا بشن . ما باید جوری پیکربندیش کنیم و بهش بگیم که این اسکریپت bayand ما رو هم به عنوان یک سرویس اجرا کن وقتی سیستم بوت میشه . 

 

systemd با یه مفهومی به اسم unit کار میکنه . systemd حدود ۱۱ نوع unit داره (شاید عددشو دارم اشتباه میگم :)‌ ). کارش اینه که این unit هارو مدیریت کنه . ببینه کی فعالشون کنه کی غیر فعالشون کنه و این حرفا . یه نوع از این unit ها همون service ها هستند . 

برای اینکه برای systemd یک unit از نوع سرویس تعریف کنیم باید یک فایل پیکربندی با پسوند service. براش درست کنیم . راه اول اینه که بشینیم man page های systemd رو بخونیم تا بفهمیم این فایل های پیکربندی چجوری هستند و راه دوم و ساده ترش اینه که فایل پیکربندی یه سرویس های دیگه رو برداریم و تغییرش بدیم تا ازش به عنوان فایل پیکربندی سرویس خودمون (bayand) استفاده کنیم :)

 

systemd فایل های پیکربندیشو در مسیر های مختلفی قرار میده ولی یکی مسیر هایی که من تجربه کارباهاشو دارم ، مسیر زیر هستش :

/etc/systemd/system

در این مسیر یک سری فایل های پیکربندی unit های مختلف systemd هست . ما فایل های پیکربندی سرویس ها رو میخوایم یعنی اونایی که پسوندشون service هست . با دستور زیر لیست این فایل های پیکربندی رو بدست میاریم :

ls /etc/systemd/system/*.service

 من یه فایلی دارم در این مسیر به نام syslog.service محتویات همین فایل رو ببینیم :

[Unit]
Description=System Logging Service
Requires=syslog.socket
Documentation=man:rsyslogd(8)
Documentation=man:rsyslog.conf(5)
Documentation=https://www.rsyslog.com/doc/

[Service]
Type=notify
ExecStart=/usr/sbin/rsyslogd -n -iNONE
StandardOutput=null
Restart=on-failure

# Increase the default a bit in order to allow many simultaneous
# files to be monitored, we might need a lot of fds.
LimitNOFILE=16384

[Install]
WantedBy=multi-user.target
Alias=syslog.service

خب به طور کلی این فایل کانفیگ به سه بخش تقسیم شده . بخش [Unit] , [Service]  و [Install] که بالای هر بخش اسم اون بخش داخل کروشه نوشته شده . 

داخل بخش Unit یک سری اطلاعات عمومی راجع به این unit فارغ از هر نوعی که هست (مثلا سرویس یا هر نوع دیگه ای) مثل توضیح کوتاه کارکردش ، داکیومنت هاش و ... مشخص میشه . 

داخل بخش Service اطلاعات خاص سرویس نوشته میشه مثلا اینکه فایل اجرایی سرویس چی هست و چطوری و تحت چه شرایطی باید اجرا بشه و این حرفا . 

داخل بخش Install هم معمولا اطلاعات مربوط به ارتباط این سرویس با unit های دیگه نوشته میشه مثل اینکه مثلا فلان unit برای کارکرد صحیحش به این سرویس نیاز داره .

 

خیلی عمیق نشید ما همه ی اینها رو نمیخوایم از بخش Unit فقط Description که مشخص کننده یه توضیح کوتاه متنی در مورد سرویس هست رو میزنیم . از بخش Service فقط ExecStart رو مشخص میکنیم که میگه برای فعال کردن سرویس کدوم فایل باید اجرا بشه و بخش Install رو هم نمیخوایم . 

نهایتا یه فایل کانفیگ ساده برای سرویس ما اینطوری میشه :

[Unit]
Description=Bayan Weblog Tracking Service for linux

[Service]
ExecStart=python3 -u /home/hossein/Projects/bayand/bayand.py

در بخش Description یه توضیح کوتاه از کارکرد این سرویس یا به طور کلی این unit نوشتیم . و قسمت ExecStart هم میگه وقتی میخوایم سرویس فعال بشه چه دستوری باید اجرا بشه . من گفتم بره با مفسر پایتون اون اسکریپتی که قسمت قبلی نوشتیم رو اجرا کنه .

دقت کنید پارامتر u- رو حتما برای مفسر پایتون استفاده کنید همینطور که ماهم استفاده کردیم . در حالت عادی هر چیزی که توی اسکریپتتون پرینت میکنید (به خروجی استاندارد یا ارور استاندارد میفرستید) به عنوان log برای systemd ثبت میشه . به دلایلی اگر این پارامتر u- رو نذارید این اتفاق نمیفته یعنی دستورات print که میزنید لاگ نمیشن . دلیلشو خودتون در موردش تحقیق کنید اگر هم خواستید بگید تا در کامنت توضیح بدم براتون . 

 

خب این فایل رو با اسم bayand.service در مسیر etc/systemd/system که قبلا اشاره کردیم ذخیره میکنیم  .

حالا یک بار دستور زیر رو اجرا میکنیم تا systemd مجددا فایل کانفیگ unit هارو بارگذاری کنه این باعث میشه فایل کانفیگ جدیدی که ما نوشتیم هم بارگذاری بشه :

sudo systemctl daemon-reload

 

تبریک میگم همه چی آمادس :)))

 

حالا فقط کافیه سرویسمون رو اجرا کنیم . برای اجرای سرویسمون از دستور زیر استفاده میکنیم :

sudo systemctl start bayand

 دقت کنید systemd یه سرویس رو با همون اسمی که فایل کانفیگشو ذخیره کردید میشناسه . برا همین ما اونجا bayand.service ذخیره کردیم .

 

برای اینکه چک کنیم سرویسمون به درستی فعال شده از دستور زیر استفاده میکنیم :

همینطور که در تصویر میبینید سرویسمون active و شاد و شنگول داره کار میکنه . 

 

توی systemd ما میتونیم یک سرویس رو enable کنیم . enable کردن یک سرویس باعث میشه با هر بار بوت سیستم اون سرویس به طور خودکار فعال بشه . همینطور در مقابل میتونیم یک سرویس رو disable کنیم که باعث میشه دیگه با هر بار بوت سیستم فعال نشه . بیاید سرویسمون رو enable کنیم که خودش خودکار اجرا بشه :

sudo systemctl enable bayand

 

از این به بعد با هر بار اجرا خودش خودکار فعال میشه سرویسمون . 

فقط یه کار مونده . الان سرویسمون همه چیزو توی فایل newPosts داخل مسیر tmp/ ذخیره میکنه . شما هرجور که میخواید میتونید از اطلاعات این فایل استفاده کنید مثلا بگید اینارو ایمیل بزنه بهتون . بگید اینارو با گویش کامپیوتری بخونه براتون یا هر کار دیگه ای ....

اینجا میخوایم هربار که ترمینال رو باز میکنیم بالای ترمینال بهمون نشون بده . داخل مسیر home یوزر خودتون یه فایلی هست به نام bashrc. (دقت کنید اولش یه نقطه داره) . این یک اسکریپت bash هستش که هر بار که داخل لینوکستون ترمینال رو اجرا میکنید  خودکار اجرا میشه همون اول کار. داخلش دستوراتی هست که محیط ترمینال شما رو آماده میکنه . کاری که میکنیم اینه که این فایل رو ویرایش میکنیم و چند تا دستور به آخرش اضافه میکنیم که بیاد هردفعه محتویات اون فایل newPosts رو برای ما با دستور cat روی صفحه نشون بده . 

 

دستورات زیر رو به آخر فایل bashrc. اضافه میکنیم :

if [[ $(wc -c /tmp/newPosts | cut -d" " -f1) != "0" ]]
then
        echo "----- NEW WEBLOG POSTS -----"
        echo
        cat /tmp/newPosts
        echo 
        echo "----------------------------"
fi

 شرط گذاشتیم که اگر فایل newPosts خالی نبود بیا محتویات اون رو با دستور cat روی صفحه نشون بده . به همین سادگی 

حالا تغییرات فایل رو ذخیره کنید و یک بار ترمینال جدید باز کنید و میبینید که پستای جدید از این به بعد به شما نشون داده میشه (اگر کسی پست گذاشته باشه البته اگر پست جدیدی نباشه و فایل newPosts خالی باشه چیزی نشون داده نمیشه ) :

 

اینم به عنوان نکته آخر بگم که میتونید با دستور journalctl که یه بخش از همون systemd هست لاگ های سرویسمون رو ببینیم :

 

امیدوارم که لذت برده باشید :)

موافقین ۵ مخالفین ۰

خیلی خوب و کامل

خوشحالم که اینطور بوده :)

واقعا نوشتن کد علاوه بر مهارت، یه خلاقیت و تیزهوشی خاصی هم می‌خواد که هیچوقت در من نبود. متاسفانه. ولی دم شما گرم. 

بله به هر حال مثل هر کار دیگه ای سختی های خودشو داره 
به نظر من تمرین و تکرار مهمتر از تیزهوشی که‌ میگید هستش ...
ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">