بایگانی برچسب: s

داستان پروژه جبیر – رویای نوجوانی استیو جابز شدن (قسمت اول)

احتمالا اگر وبلاگ یا محتوایی که من تولید می‌کنم رو دنبال کرده باشید، با مفاهیم و اسامی خاصی من رو به یاد خواهید آورد. چه مثل چند ماه اخیر با پروژه‌های بینایی ماشین ، چه روبی و ریلز که چندین ساله کم کم با اون شناخته می‌شم، چه لینوکس و سخت‌افزار و این داستان‌ها. احتمالا هم اگر از دنبال‌کنندگان این وبلاگ باشید، می‌دونید که داستان برنامه‌نویس شدن من (قسمت اول، قسمت دوم) چیه و چطور شد که من شدم اینی که هستم.

اما قطع به یقین، خیلی از دوستان قدیمی‌تر من رو با «پروژه جبیر» یا «جبیر او اس» یا «سیستم‌عامل جبیر» می‌شناسند. پروژه‌ای که من رو با جدیت وارد دنیای توسعه نرم‌افزار، نرم‌افزار آزاد و جامعه کاربری گنو/لینوکس ایران کرد. در این پست، قصد دارم تا در مورد پروژه جبیر کمی بنویسم. در واقع، قصد من اینه که داستان این پروژه رو تعریف کنم و بگم که چی شد که اینطوری شد 🙂

چرا این مطلب نوشته شد؟

حقیقتا از سال ۹۴ به بعد که دیگه وبسایت پروژه جبیر آپدیت نشد و حتی از برند جبیر برای پروژه‌ای استفاده نشد، دلم نخواست که راجع بهش چیزی بنویسم. چرا که این پروژه علیرغم تمام خوبی‌ها و آموزه‌هاش برای من، خاطرات بدی هم داشت و خب هرچیزی، لازمه که روزی کنار گذاشته بشه. در حقیقت، جایی که انسان حس می‌کنه باید رها کنه، باید رها کنه و برای من این زمان سال ۹۴ بود. زمانی که همه‌جا اعلام کردم پروژه جبیر، چه در قالب «توزیع لینوکس» و چه در قالب «نسخه‌ای از BSD» دیگر عرضه نخواهد شد.

اما چندی پیش، پای یکی از پست‌های جبیر (لینک) نظری دریافت کردم (که البته تایید نشده) و در بخش آمار وبگاه (که به کمک افزونه Jet Pack بررسی می‌کنم) هم متوجه شدم که افرادی هستند که در حال رصد کردن گذشته من هستند. یکی از چیزهایی که عمیقا بهش باور دارم اینه که نباید در گذشته افراد زیاد کند و کاو کرد، چرا که تهش شما یا خودت ضایع میشی یا چیزی که دنبالش می‌گردی چیزی در حد زیربغل مار خواهد بود. پس با این حساب، تصمیم گرفتم که در یک سلسله مطلب جامع، داستان جبیر او اس رو جمع کنم.

حالا وقت اینه که حدودا ده سال در زمان سفر کنم و برسیم به سال ۸۹-۹۰ که این پروژه رو استارت زدم، بگم چی شد که این پروژه به ذهنم رسید و چطور شد که رفتم سمت لینوکس و … .

جرقه‌های اولیه

بسیاری از افرادی که من رو می‌شناسند، از ارادتی که نسبت به استیو جابز دارم، خبر دارند. سال حدود ۸۹ بود و من در مجلاتی که اون زمان به صورت روتین از قیمت فلان گوشی و فلان کامپیوتر و فلان کارت گرافیک می‌نوشتند از رونمایی از محصولات جدید اپل مثل iPhone 4 یا iPad می‌خوندم. بعد مدتی، با استیو جابز و زندگی اون آشنا شدم و فهمیدم که این بابا، آدمی بوده که خیلی خیلی از صفر شروع کرده (تقریبا بر خلاف خیلی از ابرپولدارهای سیلیکون‌ولی، ایشون اصلا خونواده متمول و حتی اهل فنی نداشته و خونواده‌ای که درش رشد کرده بوده یک خونواده خیلی معمولی بوده).

خلاصه آشنایی با استیو جابز، بعدش خریدن یک iPod Touch 3G در من جرقه‌ای روشن کرد. جرقه‌ای مبنی بر این که «من باید دنیا را تغییر بدم». تغییر دنیا، کار سختیه. خیلی از ما جایی از زندگی این قصد رو داشتیم ولی کار خاصی براش نکردیم. خیلی‌ها هم حرکتایی زدیم ولی بعدا سرمون به سنگ خورده. خلاصه که خیلیامون اونقدری دیوانه بودیم که روزی بخوایم دنیا رو تغییر بدیم و به قول استیو جابز، افرادی که اونقدر دیوانن که فکر می‌کنن می‌تونن دنیا رو تغییر بدن، دقیقا همونایین که دنیا رو تغییر میدن.

در همون سال‌ها بود که ما مهاجرتی از تهران به بندرعباس داشتیم و خب حقیقتا این مهاجرت و دوری از فضای تهران – بویژه محله‌ای که درش بزرگ شده بودم و طبیعتا بسیاری از هم‌کلاسی‌های دبیرستانم هم قرار بود همون بچه‌های راهنمایی و دبستان باشند – باعث شده بود کمی ناامید و افسرده باشم. تمام این دلایل دست به دست هم دادند که من تصمیم بگیرم که بخوام استیو جابز دوم باشم (شاید اشتباه همین بود، هوم؟).

خلاصه شبانه‌روز در حال ایده‌پردازی بودم. اما ایده‌ها همین جا متوقف نشدند. ایده‌ها خیلی بیش از اون چه که فکر کنید پیش رفتند در ذهنم. اما نیاز داشتم یک محرک خیلی اولیه داشته باشم. نمی‌دونستم چه محرکی ولی بهرحال یک محرک نیاز بود.

محمدرضا حقیری (چپ) و رضا باقرزاده (راست) - توسعه‌دهندگان پروژه جبیر

من باید سیستم‌عامل بسازم

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

نمی‌دونم شما چقدر با نشریات قدیمی آشنایید ولی نشریه مورد علاقه من، یا بهتر بگم یکی از نشریات مورد علاقه من، مجله دانشمند بود. مجله دانشمند مطالب علمی و فنی جالبی داشت. در اون می‌شد از ژنتیک و زیست‌شناسی تا هوش مصنوعی و … رو خوند و یاد گرفت و لذت برد. در بسیاری از شماره‌هاش، کارهای عملی رو توضیح می‌داد که شما می‌تونستید در خانه انجام بدید و … . خلاصه کلام که یکی از بهترین نشریاتی بود که می‌خوندم.

در تابستان ۸۹ یا ۹۰ بود که درست یادم نیست؛ در یکی از شماره‌های دانشمند کتاب «سیستم‌های عامل: طراحی و پیاده‌سازی» اثر «اندرو استوارت تنن باوم» معرفی شده بود. به صورت خلاصه بگم، در این مطلب اومده بود که انگیزه تنن‌باوم از نوشتن این کتاب چی بوده و چه فرایندی (بسته شدن کد منبع یونیکس نسخه ۷) باعث شد که سیستم‌عامل خودش رو از بیخ بنویسه و بعد از اون، شروع کنه به این که مراحل توسعه رو مستند کنه و در قالب یک کتاب برای دانشجویانش و هم‌چنین علاقمندان عرضه‌ش کنه.

اما این کل ماجرا نبود. آخر این مطلب اشاره شده بود که این کتاب و این سیستم‌عامل (مینیکس) باعث شدند که دانشجوی فنلاندی بی‌اعصاب، یعنی لینوس تروالدز؛ برای این که بتونه با مینیکس درست و حسابی کار کنه و گروه‌های گفت‌وگو رو بخونه و … یه سری ابزار توسعه بده و در همین حین یک هسته هم از بیخ و بن بنویسه. در ادامه توضیح داده شد که لینوس تروالدز یک باره هاردش رو نابود کرد (و خب شاید این نابودی یک‌باره هارددیسک که در میان لینوکسی‌ها شایعه، از همین قضیه نشات بگیره 😂) و این نابودی باعث شد که سیستم‌عامل خودش – که ملغمه‌ای از ابزارهای پروژه گنو و کرنلش بود – رو روی دستگاهش نصب کنه.

در ادامه کمی به تاریخچه لینوکس و دعواهای روتین تروالدز با بقیه اشاره کرده بود. این بخش کاملا من رو شیر کرد. من این بند رو که خوندم (و دقیقا یادمه که داخل یک خودرو هم بودیم که من این مطلب رو خوندم) با صدای بلند گفتم که «من باید سیستم عامل بسازم» طوری که خونواده هم نگاهشون به سمتم برگشت. خلاصه که این شد که من تصمیم گرفتم که اولین پروژه خیلی جدی زندگیم، یک سیستم عامل دسکتاپ باشه.

نخستین مطالعات، نخستین پیاده‌سازی‌ها

خب من بعد از خوندن اون مطالب یادمه که کتابی به اسم «کلید لینوکس» که آموزشش بر مبنای «اوبونتو ۱۰.۰۴» بود رو خوندم و خیلی چیزا ازش یاد گرفتم. در عین حال، روی یک ماشین مجازی اوبونتو نصب کردم و کمی از آموزش‌هایی که از لینوکس دیده بودم بهره بردم که ببینم چه خبره و دنیاش دست کیه. بعد از اون خلاصه اینطور شد که یک روز تصمیم گرفتم اوبونتو ۱۱.۰۴ (یا دقیق یادم نیست، ۱۱.۱۰) رو روی لپتاپم نصب کنم و حین نصب کل دیتام هم پرید.

بعد از این نصب، شروع به این کردم که یاد بگیرم که چطور می‌تونم شخصی‌سازی کنم و تا حد خوبی هم موفق بودم. اما هنوز کلی علامت سوال در ذهنم بود. به همین خاطر، کاری که کردم این بود که وارد فروم اوبونتو شدم و این سوالات رو پرسیدم. این‌گونه بود که ماجرای عریض و طویل جبیر، آغاز شد …

این داستان ادامه دارد …

تا همین الان، این مطلب شدیدا طولانی شده. به همین خاطر این مطلب رو اینجا قطع می‌کنم و اجازه می‌دم که شما حدس بزنید باقی ماجرا چی شد. البته دروغ چرا، باقی ماجرا رو خیلی زود (شاید حتی فردا شب) در وبلاگ منتشر می‌کنم و منتظر بازخوردهای شما می‌مونم.

امیدوارم که این مطالب، اطلاعات خوبی به شما از روند یک پروژه اوپن سورس که از قضا در جاهای مختلفی به شدت اشتباه زده؛ بده و براتون مفید واقع بشه. از این که وقت گذاشتید و این مطلب رو خوندید، ممنونم.

Share

چگونه در ده دقیقه، یک فراجستجوگر بسازیم؟

چندین روز پیش، شخصی در لینکدین خبری از ساخته شدن یک فراجستجوگر داده بود که به شخصه برای من موضوع جالبی بوده همیشه. منتها طبق عادات مالوف هموطنانمون، بزرگ حرف زدن و زیادی مبالغه‌کردن هم می‌شد در اون حرف‌ها دید. چیزی که ساخته شده بود اینطور توضیح داده شده بود که:

فراجستجوگر ساخته شده توسط تیمی از بهترین متخصصان که در یک دانشگاه خاص درس خواندند (که خب همین جملات، بدون توجه به اسم دانشگاه و موسسه و … معمولا پرچم قرمزی در بحث تولیدات ملی و بومیه) به این شکل کار می‌کنه که نتایج جستجو رو از وبسایت‌های معروف به موتور جست و جو مانند گوگل، داک‌داک‌گو، بینگ و … برمی‌گردونه و رد پای شما رو از جست و جو حذف می‌کنه.

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

آشنایی با searx

خب searx یک نرم‌افزار آزاده که هدفش، بهبود تجربه جست و جوی افراد در اینترنته. این نرم‌افزار، به دو صورت قابل دسترسیه. اول این که تعدادی نمونه عمومی داره (لینک نمونه‌های عمومی در اینجا قرار گرفته) و هم به صورت «خودمیزبان» یا همون self-hosted. متد خودمیزبان یعنی شما به عنوان کاربر، می‌تونید به صورت رایگان یا با پرداخت پول (بسته به مدل کسب و کار و توسعه اون پروژه خاص)، اون نرم‌افزار رو روی هاست یا سرور مورد نظر خودتون نصب کنید.

در این آموزش، قراره با کمک یک سرور لینوکسی، یک زیردامنه، یک کارساز وب و داکر؛ یک فراجستجوگر ساده رو به کمک هم بیاریم بالا. به این شکل می‌تونیم هم یک نمونه عمومی عرضه کنیم، هم این که دیتای کمتری در اختیار شرکت‌هایی مثل گوگل یا مایکروسافت بذاریم.

ساخت فراجستجوگر

برای ساخت فراجستجوگر خودمون، نیاز به موارد زیر داریم:

  • سرور لینوکسی. من شخصا از اوبونتو ۱۸.۰۴ استفاده کردم. برای پردازش بهتر نتایج و نخوردن به مشکل تحریم و …؛ بهتره که سرور داخل ایران هم نباشه. به همین خاطر، من از سرور هلند استفاده کردم (کشور محل قرارگیری سرور، کاملا به خودتون بستگی داره).
  • یک دامنه یا زیردامنه. برای این پروژه من از searx[dot]haghiri75[dot]com استفاده کردم.
  • کمی آشنایی به کارهای سروری. اگر آشنایی خاصی ندارید هم مهم نیست! در حد لزوم در این مطلب یاد می‌گیرید 😁

آماده‌سازی سرور

وقتی سرور رو از ارائه‌دهنده سرور تحویل گرفتیم (با فرض اوبونتو/دبیان بودنش) نیازه تا اول لیست بسته‌های اون رو کمی به روز کنیم:

sudo apt update

و اگر لازم شد، کل سیستم‌عامل هم یک بار به‌روز می‌کنیم:

sudo apt full-upgrade

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

sudo apt install nginx python3-certbot-nginx docker.io

خب ببینیم این بسته‌ها برای چین؟

  • nginx: این بسته، وب‌سرور یا همون کارساز وب ماست. چیزی که باعث میشه ما بتونیم بدون مشکل، یک وبسایت یا نرم‌افزار تحت وب رو استفاده کنیم.
  • python3-certbot-nginx: از این بسته استفاده خواهیم کرد تا یک گواهی SSL برای وبسایت خودمون بگیریم.
  • docker.io: داکر یک سیستم کانتینرییزشنه. در واقع نرم‌افزارها رو داخل بسته‌های کوچولو قرار می‌ده و همه ملزوماتشون اونجاست. فقط تنها موردی که داره، اینه که از هسته سیستم عامل استفاده می‌کنه برای مدیریت فرایندها (در واقع تفاوتش با ماشین مجازی همینه).

حالا ما سرور رو آماده کردیم. گام بعدی چیه؟

آماده‌سازی دامنه

برای آماده‌سازی دامنه، کافیه که یک رکورد A با IP سرور مورد نظر ایجاد کنید. البته در بعضی موارد از CNAME هم میشه استفاده کرد اما اینجا چون سرور از وبسایت جدا بود، یک A تعریف شد. بعد از این که رکورد رو تعریف کردیم، باید ۵ تا ۱۰ دقیقه صبر کنیم تا عموم DNS Server های اینترنت، بشناسنمون. بعدش می‌تونیم به کارمون ادامه بدیم.

حالا ۱۰ دقیقه گذشت و یک قهوه هم خوردیم و آماده‌ایم که مرحله بعدی رو انجام بدیم.

دریافت گواهی SSL

خب دریافت گواهی SSL هم بسیار ساده‌ست. کافیه این دستور رو در سرور اجرا کنید (و دامنه من رو با دامنه خودتون عوض کنید):

sudo certbot -d searx.haghiri75.com --nginx

در این مرحله شما باید آدرس ایمیلتون رو وارد کنید و به چند سوال هم پاسخ بدید. در کل همه‌چیز با یک wizard اتفاق میفته و نیازی نیست که زحمت زیادی بکشید. فقط یک نکته مهم رو اینجا باید بهش دقت کنیم. اون نکته اینه که certbot اینجا خودش nginx رو استارت می‌زنه. در مرحله بعدی، نیاز داریم که به این مهم توجه کنیم.

راه‌اندازی داکر و نصب فراجستجوگر

خب اول از همه کاربر خودمون (که در اینجا فرض می‌گیریم نام کاربریش هم Ubuntu ئه) رو به گروه داکر اضافه می‌کنیم:

sudo usermod -aG docker ubuntu

بعدش کافیه یک بار از نشست SSH خارج شیم و دوباره به سرور SSH بزنیم. دقت داشته باشید که این بخش الزامی نیست؛ ولی اگر شما این کار رو نکنید بعدا در استفاده از داکر، نیازمند دسترسی ریشه خواهید بود. نگران دسترسی ریشه هم نباشید چون با sudo قابل حله.

بعد از این مورد، ایمیج searx رو از رجیستری داکر دریافت می‌کنیم:

docker pull searx/searx

خب در حال حاضر، اتفاق خاصی می‌افته؟ خیر. فقط تصویری که searx روی اون نصب شده، روی سرور ما دانلود شده.

بعد از اون، نیازداریم که یک کانتینر براش بسازیم. برای این، مراحل زیر رو طی می‌کنیم:

mkdir searx
cd searx
docker run --rm -d -v ${PWD}/searx:/etc/searx -p 8080:8080 -e BASE_URL=http://localhost:8080/ searx/searx

خب تبریک به شما، الان شما یک فراجستجوگر دارید.

اما صبر کنید! هنوز نمی‌تونیم بهش دسترسی پیدا کنیم. پس چه کنیم؟

پراکسی معکوس برای دسترسی به محتوا

خب اینجا نیاز داریم که از پراکسی معکوس استفاده کنیم. انجینکس علاوه بر این که وب‌سروره، پراکسی معکوس هم هست و خیلی از ما عمدتا از قابلیت پراکسی معکوسش برای اجرای نرم‌افزارهای تحت وبمون استفاده می‌کنیم. مثل همین آموزش دپلوی کردن یک پروژه ریلز نوشته بودم (لینک). دونستن این که پراکسی معکوس چیه و چی کار می‌کنه، از ملزومات پایه‌ای مدیریت سیستم و همچنین دواپس و CI/CD محسوب میشه (جهت اطلاعات بیشتر این پست رو بخونید).

پس اگر می‌خواهید در آینده مهندس DevOps بشید، شاید بتونید این مطلب رو فرصتی برای تمرین یکی از مواردش قرار بدید. فکر کنم زیاد صحبت کردیم. بریم سر اصل مطلب. برای این که بتونیم از پراکسی معکوس استفاده کنیم، کافیه که اول با ادیتور دلخواهمون، فایل پیکربندی رو باز کنیم:

sudo nano /etc/nginx/sites-enabled/default

و سپس دنبال دامینمون بگردیم (در نانو با ctrl + W میشه). بعد از این که دامینمون رو پیدا کردیم کافیه بخش location / رو پیدا کنیم (معمولا دو سه خط پایین‌تر از دامین و تنظیماتشه) و سپس به این شکل درش بیاریم:

location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                # try_files $uri $uri/ =404;
                proxy_pass http://localhost:8080;
        }

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

sudo systemctl restart nginx

استفاده از فراجستجوگر شخصی

سخن آخر

نرم‌افزار searx مثل هر نرم‌افزار متن‌باز و آزاد دیگری، قابلیت شخصی‌سازی داره و همین موضوع که با زبان پایتون نوشته شده هم نشون میده که شخصی‌سازیش احتمالا از چیزی که فکر می‌کنیم، ساده‌تره. به همین خاطر می‌تونیم به سادگی این نرم‌افزار رو تغییر بدیم که مطابق میل خودمون کار کنه و طبیعتا آموزشش هم در اینترنت وجود داره.

موضوع بعدی اینه که فراجستجوگرها، علاوه بر این که می‌تونن در حفظ حریم شخصی و … موثر باشند، می‌تونن کاملا بیزنسی هم کار کنند. مثلا هرکلید واژه‌ای که سرچ کنید رو صرفا در موضوع خاصی دنبالش بگردند. مثلا شما اگر سرچ کنید «سیب‌زمینی» فقط در وبسایت‌هایی که وبینار میزبانی می‌کنند دنبالش بگرده. وقتی سرچ می‌کنید «قشم» فقط در وبسایت‌های گردشگری دنبالش بگرده و الی آخر.

در این مطلب قصد داشتم این موضوع رو نشونتون بدم که داشتن یک موتور جست و جوی امن، اونقدرا که فکر می‌کنید سخت نیست و با کمک نرم‌افزارهای آزاد، به سادگی می‌تونید یکی رو خودتون بسازید. در پایان مطلب، جا داره از شما بابت خوندن این مطلب تشکر کنم. همچنین، ممنون میشم مطالب و خط‌خطی‌های من رو در ویرگول هم بخونید و نظر بدید 🙂



Share

داستان برنامه‌نویس شدن من – قسمت دوم

در پست پیشین، یعنی قسمت اول داستان برنامه‌نویس شدنم (لینک) از زمانی که شروع به خوندن کتاب‌های ویژوال بیسیک کردم تا زمانی که پروژه جبیر رو راه انداختم رو به تفصیل توضیح دادم. فکر می‌کنم داستان برنامه‌نویس شدن من، داستان جالبی برای خیلی از دوستانی که وبلاگم رو میخونن بوده و به همین دلیل، تصمیم گرفتم که قسمت دومش هم حتما بنویسم.

همونطوری که در قسمت قبلی قولش رو داده بودم، قراره که در این قسمت از بعد از پروژه جبیر تا زمانی که وارد بازار کار شدم رو توضیح بدم و بگم چی شد که اینطوری شد. در مورد مسیرهای شغلی قبل‌تر توضیح دادم (مثلا در پست چگونه توزیع لینوکس بسازیم و یا پست چگونه بازی‌ساز شویم) همینطور حتی ابزارها و وسایلی که در مسیر شغل‌های مختلف طراحی و تولید کردم (مثل صداگذاری روی بازی کامپیوتری) هم در این وبلاگ پیش‌تر توضیح دادم. فلذا در این مطلب، اصلا و ابدا به مسیرهای شغلی اشاره نخواهم کرد.

ورود به دانشگاه

در طی این سالها، یعنی از حدود ۹۱ تا ۹۳ راه‌های زیادی رو رفتم که سرویس‌ها و نرم‌افزارهای خاصی رو طراحی کنم و خب دروغ چرا، تا حد زیادی هم رویای استیو جابز یا زاکربرگ شدن هم در سر داشتم و خب کارهای مختلفی مثل ایجاد انجمن‌های اینترنتی مختلف (ایران‌بی‌اس‌دی، ایران‌هکینتاش و …) گرفته تا برپا کردن شبکه‌های اجتماعی و نرم‌افزارهای آنلاین دیگر (اکسوال، نکست‌کلود و …) رو انجام می‌دادم. راستش این راه‌ها من رو به قول خارجی‌ها Satisfy نمی‌کرد و همچنان دنبال این بودم که یک سیستم عامل خوب بسازم!

خلاصه شد سال ۹۲ و ما از شهر بندرعباس به تهران برگشتیم. اون سال، سال پیش‌دانشگاهی من بود (و بد نیست این داستانکم رو هم پیرامونش بخونید) و اون سال، یک تصمیم بزرگ هم گرفتم. تصمیمم این شد که جبیر به جای این که مبتنی بر اوبونتو (یک توزیع از گنو/لینوکس)، یک نسخه شخصی‌سازی‌شده از FreeBSD باشه. از همین رو، شروع کردم به رفتن به IRC های مختلف، سوال پرسیدن و مستندات خوندن. بعد از چندین ماه مطالعه، وضعیت اینترنت خونه و خودم تا حد خوبی پایدار شد و بعد شروع کردم به انجام تغییرات روی کد FreeBSD.

بعد از مدتی، پروژه جبیر تا حد خوبی پیش رفت و گذشت و گذشت و من کنکور دادم (داستانی از کنکور هم اینجا نوشتم) و وقتی نتایج اومد، فهمیدم که در دانشگاه آزاد اسلامی واحد تهران مرکز در رشته مهندسی کامپیوتر و گرایش سخت‌افزار قبول شدم.

داستان برنامه‌نویس شدن من - محمدرضا حقیریشرکت در لاگ‌ها و رویدادها و آخر و عاقبت پروژه جبیر

حضور در تهران و دانشجو شدن، به من کمک کرد که وارد جامعه بشم و در رویدادهای نرم‌افزار آزاد و متن‌باز و سایر رویدادها (مثل PyCon و …) شرکت کنم. اولین رویدادی که شرکت کردم، رویدادی بود به اسم «جامعه رایانش ابری آزاد». در اون رویداد با KVM و Docker آشنا شدم و تا حد زیادی هم دانشم در زمینه Containerها و مجازی‌سازی تا حد خوبی بالا رفت.

در حاشیه شرکت در این رویدادها، بسیاری از افرادی که از انجمن اوبونتو و یا تکنوتاکس یا لینوکس‌ری‌ویو می‌شناختم رو حضوری دیدم و باهاشون آشنا شدم و حتی رفاقت‌هایی شکل گرفت. پس از مدتی، در بحثی دوستانه، تصمیم بر آن شد که پروژه جبیر کلا منحل بشه و پروژه‌ای به این بزرگی که نیازمند دانش فنی بالا، پول زیاد و همچنین حوصله فراوونه، به زمانی موکول شه که بتونم از پس حداقل یک موردش بربیام. فلذا پروژه جبیر اعلام شد که دیگه قرار نیست ادامه پیدا کنه.

اگر دوست دارید ببینید که پروژه جبیر چه شکلی بوده، می‌تونید این لینک مربوط به وب آرکایو رو هم ببینید: لینک. در ادامه، بنا به دلایلی (که در ادامه این مطلب بهش می‌پردازیم) تصمیم شد که پروژه جبیر بیشتر روی فاز سخت‌افزاری باشه و چند مطلب هم در موردش حتی نوشتم(لینک).

داستان برنامه‌نویس شدن من - محمدرضا حقیری

یادگیری روبی، ورود به حوزه سخت‌افزار و دیگر هیچ!

مهرماه ۹۳ بود که من خیلی جدی تصمیم گرفتم حداقل یک زبان برای توسعه وب رو جدی یاد بگیرم. قبل‌ترش، کتاب «از این پس پایتون» رو خونده بودم و به همین خاطر هم کمی با پایتون و فلسک آشنا بودم. دوستی یک کتاب جنگو هم برای من ارسال کرد. اما در همون هنگام در بحثی در IRC که دقیق یادم نیست مربوط به occc بود یا لاگ کرج، دوستی به من پیشنهاد کرد که روبی و روبی‌آن‌ریلز رو یاد بگیرم. در ادامه‌ش، توصیه کرد که حتما با دیتابیس‌ها آشنا شم و کمی هم مهندسی نرم‌افزار یاد بگیرم.

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

خب همونطوری که ابتدای متن گفتم، من گرایش سخت‌افزار بودم و حقیقتا این وسط به سرم زده بود دانش سخت‌افزاری خودم رو هم بالا ببرم. به همین خاطر ترم ۳ یا ۴ که بودم، قبل از این که به مدار منطقی برسم، خودخوان شروعش کردم. برام جالب بود و خب در عین حال ریاضیات گسسته هم برای من داشت مرور می‌شد. این مرور، در کنار دانش مدار منطقی من رو وادار کرد که کمی بیشتر بخوام در این حوزه ورود کنم. به همین خاطر، معماری کامپیوتر و ریزپردازنده رو هم حتی پیش از این که درسم بهشون برسه، مطالعه کردم.

وقتی به نتایج جالبی رسیدم، تصمیم گرفتم دوباره دانشم رو با مردم به اشتراک بذارم. به همین خاطر، این بار هم محتوا رو به زبون انگلیسی تولید کردم (لینک) و به رایگان در نسخه انگلیسی همین وبلاگ منتشرش کردم. خلاصه که اینجا تموم نمیشه. در اون سالها، بازار «اینترنت چیزها» یا IoT هم داغ بود و خب طبیعتا شروع کردم به یادگیری آردوینو، رزبری‌پای و … و پروژه‌های جالبی هم با اونها انجام دادم. البته خیلی از این پروژه‌ها رو هنوز که هنوزه عمومی نکردم.

خلاصه این مورد هم گذشت و رسیدیم به شهریور ۹۶. یعنی جایی که من خیلی جدی و رسمی وارد بازار کار شدم.

داستان برنامه‌نویس شدن من - محمدرضا حقیری

ورود به بازار کار

در تیرماه ۹۶، در رویدادی شرکت کردیم که مرتبط با فعالان صنعت بازی رایانه‌ای بود. این رویداد، به طور خاص به آهنگسازان و مهندسین صدا اختصاص داشت و خب بخاطر علاقه شخصیم به موسیقی، در این رویداد شرکت کردم. آخر رویداد گپ و گفتی با سخنران رویداد داشتم که باعث شد شخصی بیاد خودش رو معرفی کنه و بگه که تیمشون نیاز به آهنگساز داره. پس از مدتی، مدیر استودیو به من پیام داد و گفت بازی‌ای در ژانر کودکه و خب نمی‌دونم چی شد که اون موقع، این بحث ادامه پیدا نکرد.

اما شهریور ۹۶ یکی از دوستانی که در همون استودیو مشغول بود، برای یک بازی دیگر من رو دعوت کرد به همکاری. یک مصاحبه ریزی داشتیم و پس از اون مصاحبه، قرار شد من برم و همکاری کنم. پس از این ماجرا، من رسما وارد اکوسیستم و بازار کار شدم تا به امروز.

سخن آخر

خب، در این مطلب هم مثل مطلب قبلی حجم خوبی از خاطرات من رو شاهد بودید. کل حرفی که می‌خواستم بزنم این بود که دوستان، از تجربه کردن و حتی شاخه شاخه پریدن؛ نترسید. این پرش‌ها به خودی خود باعث میشن که شما در کارتون – حتی کارهای فریلنسری و پروژه‌ای – به شدت موفق‌تر عمل کنید. یادتون باشه که زندگی، فان‌تر از اونیه که بخواید با زیادی جدی گرفتن؛ خرابش کنید.

موفق باشید 🙂

 

Share

توسعه عملیات، مدیریت سیستم، استقرار و یکپارچگی

در دنیای امروزی، بخش بسیار بزرگی از بیزنس و همچنین توسعه نرم‌افزار مرتبط به توسعه عملیات (Dev Ops)، مدیریت سیستم (System Administration) و همچنین استقرار و یکپارچگی ادامه‌دار (CI/CD) میشه. شاید حتی مهم‌تر از اصل نرم‌افزار، رسیدگی به این موضوعات باشه. در این پست، قراره که با هم بررسی کنیم چطور میتونیم در پایان روز، به خودمون بگیم DevOps Engineer؟ و چه چیزایی باید بلد باشیم؟ 🙂

مدیریت سیستم یاد بگیرید

یادگیری مدیریت سیستم، بخش «عملیات» قضیه رو معمولا شامل میشه. پس لازمه که اینجا چیزایی رو بلد باشیم که معمولا در شرکت‌ها و سازمان‌های بزرگ بهشون نیاز میشه. اما قبل از اون، لازمه که یه چیزایی رو به صورت عمومی بلد باشیم. پس بیاید با هم بررسی کنیم که عمومیات دواپس شدن چیا هستن؟

  • یادگیری لینوکس. عموم شرکت‌ها در دنیا در حال حاضر، سرورهای لینوکسی دارند. بلد بودن لینوکس، یک «باید» در یادگیری دواپس محسوب میشه. یادگیری لینوکس اصلا سخت نیست. کافیه یک توزیع خاص (مثل اوبونتو) رو نصب کنید و باهاش بازی کنید. کم کم دستتون میاد که چی به چیه. بعد از این ماجرا، میتونید یک سرور اجاره کنید و چیزایی که یاد گرفتید رو روش تست کنید.
  • آشنایی با وب‌سرورها. وب‌سرورها، نرم‌افزارهایی هستند که به شما امکان نمایش نرم‌افزار و محتوای تولیدی از طریق پروتکل HTTP رو میدن. در دنیای امروز اکثریت قریب به اتفاق کسب و کارهای کوچک و حتی بزرگ، از NGINX استفاده می‌کنن. پس بد نیست بعد از این که لینوکس یاد گرفتید، روی سرور یا ماشین مجازی لینوکسیتون یک وب‌سرور نصب کنید و سعی کنید یک صفحه استاتیک باهاش نمایش بدید.
  • آشنایی با شبکه. گرچه معمولا این مورد رو باید اول از همه بیاریم، اما من شخصا معتقدم که یادگیری لینوکس در بحث مدیریت سیستم به هرچیزی ارجحه. اما از این موضوع که بگذریم، چرا شبکه؟ شبکه پایه و اساس دواپسه. شما بدون بلد بودن شبکه، تقریبا هیچ کاری نمی‌تونید بکنید. اما چه حد شبکه بلد بودن خوبه؟ دقت کنید که اینجا قرار نیست ما نیروی آی‌تی یک سازمان باشیم، پس فقط کافیه که پایه‌های شبکه، آی‌پی و بعضی پروتکل‌های مرسوم (SSH, FTP, HTTP, SMTP و …) رو بدونیم و بدونیم که هرکدوم چطور و کجا کار می‌کنند.
  • آشنایی با فایروال و تامین امنیت شبکه. فکر کنم عنوان خودش گویاست. در لینوکس، ما معمولا از iptables یا اینترفیس‌هایی که براش ساخته میشن (مثلا اوبونتو UFW و دبیان apparmor رو دارند) استفاده می‌کنیم. این خیلی مهمه که شما بعنوان مدیر سیستم، در جریان باشید که چه چیزایی از بیرون در دسترسه و این حجم از دسترسی، چقدر میتونه آسیب‌زا باشه.

موارد بالا، مواردی هستند که حتما باید بلد باشید. فرقی هم نمی‌کنه که جایی استخدام شدید یا اگر قراره بشید، ازتون خواستند بلد باشید یا نه. در واقع «باید»های مدیریت سیستم موارد بالان.

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

  • استفاده از یک ابر خصوصی به جای چندین سرور عمومی. این مورد، مورد خوب و امنیه. گذشته از این که باعث میشه خیلی از موارد (مثل دیتابیس و …) از بیرون در دسترس عموم قرار نگیرند، هزینه‌ها رو هم پایین میاره. فقط حواستون باشه که در این مورد، معمولا چند چیز اتفاق می‌افته که باید بلد باشید:
    • استفاده از لود بالانسر : لود بالانسرهای مرسوم مثل haproxy میتونن نقطه شروع خوبی باشن. البته این هم در نظر داشته باشید که معمولا ارائه‌دهندگان سرویس‌های ابری؛ خودشون هم لود بالانسینگ رو انجام میدن.
    • استفاده از سیستم‌های مانیتورینگ : طبیعتا شما برای این که ببینید هرکجا چه اتفاقاتی می‌افته، نیاز به یک سیستم مانیتورینگ خوب دارید. در حال حاضر سرویس‌هایی مثل prometheus و zabbix وجود دارند. همچنین میتونید اینها رو به grafana و امثالهم متصل کنید و به شکل زیبایی، اونها رو ویژوالایز کنید.
  • استفاده از نرم‌افزارهای بیلد شده به صورت سفارشی. گرچه این مورد رو شخصا درک نمی‌کنم (چون نسبت به نرم‌افزاری که از کانال رسمی – مثل مخزن‌های توزیع لینوکستون – نصب می‌کنید ممکنه امنیت و پایداری کمتری نشون بدن) اما برخی سازمان‌ها ممکنه وب‌سرور، کامپایلر یا مفسر یا حتی کرنل رو خودشون از نو بیلد کرده باشن. پس یادتون باشه این مورد هم تا حدی یاد بگیرید که اگر نیاز به بیلد مجدد شد گیر نکنید 😁

در مورد مدیریت سیستم به قدر کافی یاد گرفتیم، دیگه چی می‌مونه؟ نظر من رو بخواید الان وقتشه که یک سری ابزار رو با هم بررسی کنیم. توجه کنید که ابزارهایی که در این بخش ازشون حرف می‌زنم، ابزارهایی هستند که خودم باهاشون تجربه کار دارم. فلذا اگر ابزاری از قلم افتاده، در بخش نظرات در مورد ابزارهای مورد نظر خودتون صحبت کنید. من خوشحال میشم 🙂

ابزارهایی که باید یاد بگیرید

وب‌سرور

گرچه این رو در بخش قبلی اشاره کردم، در اینجا میخوام صرفا کمی در مورد NGINX حرف بزنم. یادتون باشه که NGINX امروزه یک انتخاب خوبه چون:

  • در بسیاری از توزیع‌ها، وجود داره. در حدی که خیلی از توزیع‌های سروری رو وقتی نصب کنید؛ ممکنه همراهش نصب شده باشه.
  • پیکربندی به شدت ساده‌ای داره (و خب کاش حداقل نیاز نبود ته هر خط پیکربندی شما یک سمی‌کالن بذاری)
  • ابزارهای جانبی بسیار خوبی مثل python3-certbot-nginx براش ساخته شده که امکان SSL و … گرفتن برای دامنه خاص و زیردامنه‌ها و … رو به شدت ساده می‌کنه.
  • تقریبا برای هرکاری یه آموزشی ازش هست!

ابزارهای CI/CD

خب ابزارهای CI/CD چی هستند؟ به صورت کلی، این ابزارها اینجان که کار استقرار (Deploy) و یکپارچگی (Integration) هرآپدیت با نسخه قبلی رو اتوماتیک انجام میدن. ابزارهای زیادی برای این کار وجود دارند من جمله Travis CI, Jenkins و البته معروف‌ترینشون Gitlab CI/CD (حداقل در ایران).

این ابزارها به این شکل عمل می‌کنن که یه سری فایل پیکربندی (در مورد گیت‌لب از نوع YML ) دریافت می‌کنند و اون رو بررسی می‌کنند. سپس مطابق اون، عملیات رو انجام میدند و نرم‌افزار شما رو مستقر می‌کنن. خوبی گیت‌لب در این زمینه اینه که به ازای هر به‌روز‌رسانی‌ای که شما انجام بدید، یک بار Pipeline اجرا می‌کنه و بروزرسانی‌ها رو روی سرور مورد نظر اعمال می‌کنه. البته باقی ابزارها هم امکان اتصال به گیت رو دارند پس نگران نباشید.

ابزارهای مانیتورینگ

طبیعتا بالا بودن یا نبودن سرویس‌ها، دیتابیس، سرویس‌هایی که از بیرون دریافت می‌کنیم و یکپارچگی داریم باهاشون، مهمن. همینطور ظرفیتی که در دیسک و حافظه و … اشغال شده هم مهمه که دونسته بشه. فلذا اینجا لازمه که ابزاری باشه که اینجا بیاد و این رو برای ما چک کنه.

این ابزار معمولا چیه؟ خب ابزارهای زیادی براش هست و من تجربه‌م استفاده از prometheus بوده. پرومتئوس یک سری ابزار خاص داره که بهش میگن exporter. شما روی هر قسمتی که نیاز دارید (مثلا nginx یا خود سرور که بهش میگن node یا هرچیزی از این قبیل) یک اکسپورتر نصب کنید و نتایج آنالیزها رو اینجا ببینید.

همچنین نتایج معمولا روی پرمتئوس زیبا نیستن، به همین خاطر شما میتونید یک ابزار بهتر مثل Grafana نصب کنید و نتیجه رو  به شکل قشنگی visualize کنید. همچنین میتونید روی هرکدوم یک سیستم alerting ست کنید که از روش‌های مختلفی مثل پیامک، ایمیل یا حتی پیام در اسلک بهتون هشدار بده که کجا چی درست نیست.

ابزارهای ذخیره‌سازی

خب، این هم یه چیزی که شاید کمتر ازش با خبر بوده باشید :). در دنیای امروز تقریبا کسی نیست که رو همون سروری که نرم‌افزارش هست، فایل ذخیره کنه. پس چی کار می‌کنن؟ هیچی، اونجاهایی که جزء دنیا حساب میشن؛ معمولا از Amazon AWS استفاده می‌کنن و پارتیشن S3 دریافت می‌کنن. S3 یعنی Simple Storage Solution (سه تا S) و خب این حقیقت وجود داره که راهکار بهتریه. چرا؟ چون شما برای ذخیره‌سازی صرفا هارد نیاز داری و نه پردازنده یا رم زیاد.

اما نگران نباشید، اگر به هر دلیلی دسترسی به AWS ندارید، میتونید در همین ایران از ابزارهایی مثل ابرآروان و پشتیبان هم استفاده کنید. فقط کافیه که یاد بگیرید که چطور نرم‌افزار رو با S3 یکپارچه کنید (اینجا اهمیت این ماجرا که مهندس دواپس نیازمند اینه که دانش برنامه‌نویسی داشته باشه مشخص میشه) و دستورالعمل‌های لازم رو به توسعه‌دهنده‌ها بدید؛ یا این که اصلا خودتون کدبیس رو درک کنید و این یکپارچه‌سازی رو انجام بدید.

یک راه دیگه هم داشتن سرور با حجم بالای هارددیسک (در ابعاد ترابایت) میتونه باشه. بعد از اون شما نیاز دارید تا یک نمونه S3 روی اون مستقر کنید. برای این کار میتونید از ابزاری مثل minio بهره بگیرید.

ابزارهای ارکستراسیون

ابزارهای ارکستراسیون چی هستند؟ ارکستر در موسیقی، به معنای «گروهی از نوازندگان»ــه. یعنی یک گروهی که مثلا دو نفر ویولن میزنن، یک نفر ویولا و یک نفر چلو. در دواپس ارکستر به مجموعه‌ای از سرورها یا شبکه‌ها گفته میشه که یک کار انجام میدن. تا حالا دقت کردید چطوریه که شما سرعت کارتون با توییتر در آلمان با سرعت کارتون با توییتر در آمریکا یکیه؟ یا مثلا چطوریه که شما از ایران یک عکس رو پست می‌کنید و مثلا خاله شما در آمریکای شمالی اون رو لایک می‌کنه؟!

علتش اینه که این نرم‌افزارها به عبارتی Orchestrate میشن (فارغ از بحث CDN و …) یعنی از یک نرم‌افزار و همچنین دیتابیسشون (البته دیتابیس Cache و نه دیتابیس‌های اصلی) بیش از یک نمونه در حال اجراست. برای شما سوال نشده که اینا چطور هندل میشن؟ خب جواب اینه که ابزارهای ارکستراسیون استفاده میشه.

از بین این ابزارها میشه به Docker Swarm و Kubernetes و Ansible اشاره کرد. طبق تجربه با Ansible به شما بگم که شما تنظیماتی که نیاز دارید رو مشابه CI/CD در یک سری فایل پیکربندی (انسیبل بهشون میگه استوری) می‌نویسید و مجموعه‌ای از استوری‌ها رو در یک namespace قرار می‌دید. مثلا فرض کنید همین وبلاگ کجاها قراره باشه، من یه namespace به اسم haghiri75 میسازم و اطلاعات استقرار رو بهش میدم.

با ابزارهای ارکستراسیون، آماده‌سازی و پیاده‌سازی سناریوهای سرور و یا ابر خصوصی به شدت ساده‌تر و سریع‌تر خواهد شد.

بسیار عالی، این بخش هم تمام شد. یک بخش کوچک هم مونده که اون هم میخونیم و بعدش این دفتر هم به پایان می‌رسونم. تا اینجا اگر خوندید، یکم به خودتون استراحت بدید. بعد بخش بعدی رو بخونید و یادتون نره که این مطلب رو با دوستانتون به اشتراک بذارید.

برنامه‌نویسی یاد بگیرید

بسیار خوب، در این بخش که در واقع بخش پایانی این مطلب در مورد اینه که چطور DevOps بشیم، لازمه اشاره کنم به این که نیاز دارید برنامه‌نویسی بلد باشید. حالا به چه زبونی و در چه حد؟ اینها مهمن. خب در این قسمت یکم در مورد زبان‌هایی که «باید» بلد باشید صحبت می‌کنم و بعد از اون هم راهنمایی می‌دم در مورد زبان‌هایی که احتمالا در جریان کار مجبورید باهاشون کار کنید.

پایتون، از چیزایی که باید بلد باشید!

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

  • بر خلاف گذشته که خیلی از پیکربندی‌های سرور با پرل انجام می‌شد، سالهاست که توزیع‌های مطرح لینوکس مثل اوبونتو، ردهت، دبیان، سنت‌اواس و … دارند میرن سمت پایتون. پس به نوعی شما زبانی رو یاد گرفتید که برای پیکربندی سرور داره استفاده میشه و عملا ضرری نکردید.
  • ابزارهای مانیتورینگ و همچنین پنلهایی که براشون ساخته شده هم معمولا پایتونی هستند. حداقل گرافانا که با پایتون نوشته شده و دونستن پایتون میتونه در بهبود کارکرد این قضیه به شما کمک بده.
  • احتمال خوبی هم وجود داره که نرم‌افزاری که میدن به شما تا مستقر کنید هم پایتونی باشه، فلذا پیاده‌سازی بخش دواپسی قضیه هم میتونه براتون ساده‌تر باشه.
  • و در نهایت؛ شما ممکنه ابزاری نیاز داشته باشید که موجود نباشه. پس خودتون باید پیاده‌ش کنید. با پایتون این قضیه به شدت سریع اتفاق می‌افته.

یک زبان سیستمی

زبانهای سیستمی، زبان‌های برنامه‌نویسی هستند که برای توسعه ابزارهای سیستم‌عامل استفاده میشن، برای تعامل با سخت‌افزار پرفرمنس بهتری دارند و در نهایت برای ایجاد ابزارهای زیرساختی مناسب‌ترند. اینجا نمیخوام شما رو به یادگیری اسمبلی تشویق کنم، بلکه ازتون خواهش می‌کنم همیشه نیم‌نگاهی به زبان‌هایی مثل Rust یا Go داشته باشید (و در نظر بگیرید که Go حتی در بکند هم استفاده میشه فلذا یادگیریش خالی از لطف نیست!).

زبانی که سازمان ازش استفاده می‌کنه

این هم نیاز به گفتن نداره. شما نیاز دارید تا کدبیس رو یاد بگیرید و درکش کنید. حداقل وقتی که قراره دواپسی‌جات رو روی کد اعمال کنید این مهم خودش رو نشون میده. نگران هم نباشید، معمولا DevOps درگیری به شدت کمتری با کدبیس مستقیم درگیر میشه. پس اگر حس و حال کار تو تیم توسعه‌دهنده‌ها رو ندارید نگران این مورد هم نباشید :))

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

شخصا معتقدم تجربیات ارزشمندن، اما یه نکته مهم اینه که تجربه‌ها یکسان نیستند. مثل همین مطلب، مطلبیه که من طی تجربه خودم بهش رسیدم و ممکنه شما مسیر متفاوتی رو در سفرتون به دنیای دواپس طی کرده باشید. به همین خاطر هم کل مطلب رو در یک جمله خلاصه می‌کنم که «فرمول کلی برای دواپس شدن وجود نداره».

امیدوارم مطلب مفیدی بوده باشه، در نهایت هم سال نوتون پیشاپیش مبارک 🙂

Share

چطور یک توزیع لینوکس بسازیم؟

ساخت توزیع لینوکس از جمله کارهاییه که معمولا وقتی کسی وارد دنیای لینوکس میشه دوست داره تجربه‌ش کنه. چرا؟ چون فکر می‌کنه افراد قبلی که این کار رو کردند، آدمهای خفنی بودن (که تفکر غلطی هم نیست) و فکر می‌کنند اگر دست کم یک توزیع بسازن آدم خفنی میشن (که تفکر غلطیه).

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

فکر کنم پیش‌تر به قدر کافی در مورد این که چند راه برای ساخت توزیع داریم حرف زدم. در این پست منتها قصد اینه که یک دبیان یا اوبونتویی که از پیش روی سیستم خودمون (یا ماشین مجازی) نصب شده رو به یک  ISO زنده تبدیل کنیم.

نصب و پیکربندی دبیان یا اوبونتو

در قدم اول، شما نیاز دارید که دبیان یا اوبونتو رو روی سیستم خودتون یا ماشین مجازی نصب کنید. توصیه شخصی من اینه که در دیسک یا پارتیشن جدایی نصب کنید. چرا؟ چون ما محدودیت‌هایی در ISO داریم. عموم ISO هایی که از توزیع‌های مختلف لینوکس ساخته میشن، استانداردشون iso9660 عه که یک محدودیت ۴ گیگابایتی داره. پس باید حواسمون به این موضوع هم باشه.

بعد از نصب (نصب دبیان و اوبونتو خیلی ساده‌ست : نکست نکست نکست …)، نیازه که این بسته‌ها حتما نصب بشن:

~:$ sudo apt install git mtools xorriso squashfs-tools

این بسته‌ها شامل یک سری ابزار دم دستی برای مدیریت فایل‌سیستم و … هستند. حجم زیادی هم ندارند. البته، git که معرف حضور هست برای چی استفاده میشه و خب ما قراره باهاش یه سری چیزا رو از گیت‌هاب/گیت‌لب دریافت کنیم.

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

شخصی‌سازی

خب در بحث شخصی سازی ما سناریوهای مختلفی داریم. در حال حاضر، قصد ورود به بخش‌هایی مثل تغییر لوگو و … ندارم. اما مثلا شخصی سازی میزکار کجاست؟!

شما اگر دستور زیر رو اجرا کنید:

~:$ ls -a ~

یک سری فایل و فولدر می‌بینید که با نقطه شروع شدند. این‌ها اسمشون «نقطه‌پرونده» یا «دات‌فایل»ـه. معمولا پیکربندی‌ها اینجان. این پیکربندی‌ها، تنظیمات پوسته، میزکار و … رو شامل می‌شن.

خب، حالا که در مورد این‌ها می‌دونیم با خیال راحت شخصی‌سازیمون رو انجام می‌دیم. بعدش با این دستور، پیکربندی‌هامون رو آماده انتقال به کاربران دیگر می‌کنیم :

~:$ sudo cp -r ~/.config /etc/skel
~:$ sudo cp -r ~/.local /etc/skel
~:$ sudo cp ~/.bashrc /etc/skel
~:$ sudo cp ~/.profile /etc/skel 
~:$

حواستون باشه که یک سری تنظیماتی مثل gnome-keyring در پوشه local هست که باید حذف کنید بعد انتقال.

حالا این skel چیه که انقدر مهمه؟ skel کوتاه‌شده skeleton عه. در واقع اسکلت کاربرا رو اینجا نگه می‌داریم. بعد از این که با useradd یا adduser یک کاربر جدید ایجاد کنیم، محتویات این پوشه رو برمیداره می‌بره میذاره در پوشه خانگی اون کاربر.

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

باقی شخصی‌سازی‌ها هم بیشتر به نصب نرم‌افزار و … مربوط میشن. گرچه در مورد لوگو و … توضیح زیادی ندادم اما یک تقلبی به شما می‌رسونم. اگر از دبیان استفاده می‌کنید، دنبال desktop-base بگردید و اونجا خرابکاری کنید 😁 البته راه‌های تغییر ظاهر سیستم‌های لینوکسی به اندازه راه‌های رسیدن به خداست، با کمی جست و جو و پرسشگری می‌تونید به نتیجه‌های بسیار خوبی برسید.

اسکریپت ساخت دیسک زنده

مدتها پیش در جریان ساخت کاپریس لینوکس (لینک) برای تهیه ایزوی نهایی، یک اسکریپتی نوشتم. این اسکریپت بعدها در ساخت سیستم‌عامل سانا (لینک) هم استفاده شد. در واقع، این اسکریپت تلاشی برای زنده کردن ابزارهایی مثل remastersys و relinux بود که در دوران قدیم (حوالی سال ۴۲) برای ساخت ایزوی زنده از یک سیستم لینوکسی استفاده می‌شد.

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

~:$ git clone https://github.com/Caprice-Linux/live_image custom_live

که به این شکل، پوشه‌ای به اسم custom_live برای شما ساخته میشه که حاوی اسکریپت و متعلقاتش (مثل تنظیمات گراب و syslinux) میشه. الان، ما آماده‌ایم که دیسک زنده بسازیم!

ساخت دیسک زنده

حالا، ما مقدمات ساخت دیسک رو داریم و وقتشه که دیسک رو بسازیم. ابتدا، این دستورات رو اجرا می‌کنیم :

~:$ cd custom_live
~/custom_live:$ mkdir chroot

با دستور اول وارد پوشه custom_live می‌شیم و با دستور دوم یک فولدر خالی به اسم chroot ایجاد می‌کنیم. حالا وقتشه که از rsync عزیزمون استفاده کنیم برای انتقال سیستم نصب شده به این فولدر:

~/custom_live:$ rsync -av --one-file-system \ 
--exclude=/home/* \ 
--exclude=/root/* \ 
--exclude=/tmp/* \ 
--exclude=/sys/* \ 
--exclude=/dev/* \ 
--exclude=/proc/* \ 
--exclude=/var/mail/* \ 
--exclude=/var/spool/* \ 
--exclude=/var/tmp/* \ 
--exclude=/media/* \ 
--exclude=/etc/mtab \ 
--exclude=/etc/fstab \ 
--exclude=/etc/hosts \ 
--exclude=${pwd}/chroot / chroot

خب حالا وقتشه که با یک دستور جدید به اسم chroot آشنا شیم. این دستور، کارش ارسال یک سیگنال از پردازنده‌ست که دایرکتوری ریشه رو به دایرکتوری مورد نظر ما تغییر بده. البته شرایط خاصی هم داره، مثلا این که سیستم‌عامل هر دو جا، یکی باشه. معماری یکی باشه و قص علی هذا.

با دستور chroot دایرکتوری root رو به chroot ای که ساختیم تغییر می‌دیم:

~/custom_live:$ sudo chroot chroot/

و حالا باید یک سری تغییراتی هم اینجا اعمال کنیم. این تغییرات شامل چیان؟ اول از همه دسترسی به اینترنت رو باید به قولی «یارو» کنیم. چطوری یارو کنیم؟ به این شکل :

# rm /etc/resolv.conf
# echo "nameserver 4.2.2.4" > /etc/resolv.conf

بعد از این، لازمه که اسم میزبان رو تغییر بدیم :

# echo "custom" > /etc/hostname

بعدش هم دسترسی ریشه رو یارو کنیم:

# passwd

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

# apt update
# apt install live-boot

بسته live-boot ماژول‌های مورد نیاز کرنل برای بوت شدن به صورت زنده رو هم بهش اضافه می‌کنه. در واقع به کرنل میگه که «من ازت میخوام به صورت زنده هم بتونی بوت بشی».

بعد از اضافه کردن این بسته، نوبتی هم باشه نوبت اینه که کَش apt رو پاک کنیم و یک کاربر به سیستم اضافه کنیم. به این شکل:

# apt clean
# adduser live

بعد از این که کاربر رو اضافه کردیم، لازمه که لاگین اتوماتیک رو به lightdm و یا gdm (بسته به میزکار، توزیع مبدا و … ممکنه این قضیه فرق کنه) اضافه کنیم. از اونجا که این مطلب یه آموزش عمومیه، این قسمت رو بر عهده شما میذارم.

پس از این، لازمه دسترسی sudo هم به کاربر لایو بدیم :

# echo "live      ALL=(ALL)       NOPASSWD: ALL" > /etc/sudoers.d/live

تذکر مهم: این روش به شدت ناامنه و فقط برای دیسک زنده پاسخگوعه. اگر قراره دیسکتون قابل نصب باشه، حتما در تنظیمات نصاب لحاظ کنید که به صورت NOPASSWD کاربر رو نسازه. البته، نصاب‌های مطرح معمولا این موارد رو با سوال و جواب لحاظ می‌کنند.

خب، کافیه که الان با تایپ exit و فشردن کلید اینتر از محیط chroot خارج شیم. یه سری پیکربندی ریز مونده که باید انجام بدیم. این پیکربندی‌های ریز در دبیان و اوبونتو متفاوتن ولی تفاوت اونقدری بزرگ نیست. در ادامه با هم می‌بینیم که چه تفاوتیه.

خب، همونطور که می‌دونید سیستم‌عامل برای بوت شدنش نیازمند کرنله. کرنل سیستم‌عامل و یک ‌initial ram disk برای بوت شدن دیسک زنده نیازه. حالا اینا رو از کجا بیاریم؟ ساده‌ست. از chroot مون میاریم.

در دبیان

خب در دبیان این قضیه راحته. به این شکل فایلا رو کپی می‌کنیم :

~/custom_live:$ cp chroot/boot/vmlinuz-* isotmp/live/vmlinuz
~/custom_live:$ cp chroot/boot/initrd.img-* isotmp/live/initrd.img

در اوبونتو :

در اوبونتو، اون initrd.img کمی اذیت می‌کنه. در واقع بخش اول عین دبیانه ولی بخش دوم اینطوریه :

~/custom_live:$ sudo cp chroot/boot/initrd.img-* isotmp/live/initrd.img
~/custom_live:$ sudo chown $USER:$USER isotmp/live/initrd.img

خب حالا مرحله آخر رسیده. مرحله آخر جاییه که میذاریم ISOمون پخته بشه …

ساخت ISO نهایی

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

~/custom_live:$ ./build_image.sh CustomLive.iso isotmp CUSTOMLIVE chroot

و بعد چند دقیقه ایزوی شما آماده‌ست. ایزویی که ساختید رو میتونید حالا با استفاده از qemu یا ویرچوال‌باکس و … تست کنید.

جمع‌بندی

همونطوری که دیدید، این کار گرچه از شما یه متخصص خفن نمی‌سازه، به شما یک دید بسیار بسیار خوب از کلیت قضیه ساخت توزیع میده. شاید باورتون نشه ولی خیلی از توزیع‌های مطرح امروزی مثل مینت، المنتری و …؛ از همین جاها شروع کردند و این راه شروع خوبی برای یادگیری لینوکس و سیستم‌عامله.

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

Share

اتصال به پایگاه داده SQLite در جاوا

مدتی میشه که شروع کردم به یادگیری زبان جاوا چرا که این زبان، علیرغم این که زبان قشنگ و پرکاربردیه، کمک می‌کنه برنامه‌نویس بهتری هم بشم. گذشته از اون، مفاهیم شی‌ءگرایی در جاوا به خوبی پیاده شدند و میشه تا حد زیادی هم برنامه‌نویسی و طراحی شی‌گرا رو با این زبان یاد گرفت.

خلاصه این که در ساعات بیکاری، دموی رایگان آموزش جاوای مشفق همدانی عزیز (وبسایت) رو  دیدم و کمی هم در مورد جاوا و فرمورک‌هاش و …، تحقیق کردم. خلاصه که خواستم یه پروژه فان بزنم و نتیجتا تصمیم گرفتم کمی پروژه رو چالشی کنم. به همین خاطر تصمیم گرفتم که از دیتابیس در پروژه استفاده کنم. رسیدن به این نتیجه که الان در قالب آموزش برای شما درآمده، کار ساده‌ای نبود ولی خب ارزشش رو داشت.

اسکولایت (SQLite) چیه؟

اسکولایت یک سیستم مدیریت پایگاه‌داده رابطه‌ایه که در سال ۲۰۰۰ توسط ریچارد هیپ ساخته شده. این RDBMS عزیز، برخلاف نمونه‌های بزرگ و معروفی مثل MySQL, PostgresSQL, SQL Server و … که نیازمند یک سرور جداگانه هستند، نیازی به داشتن سرور نداره و همه چیز رو در یک فایل، عموما با پسوند sqlite یا sqlite3 ذخیره می‌کنه و اطلاعاتی مثل روابط و داده‌ها رو روی اون فایل می‌نویسه.

این نوع مدیریت دیتابیس برای نرم‌افزارهایی که نیاز دارند داده رو به صورت محلی ذخیره کنند و همچنین سرویس‌های آنلاین کوچک که کاربر زیادی ندارند کاربردیه. همچنین میتونه برای ذخیره موقت اطلاعات هم استفاده بشه. به همین خاطر، محبوبیت زیادی کسب کرده. گذشته از این، در بسیاری از چارچوب‌ها مانند جنگو یا ریلز، در محیط آزمایش (test) و توسعه (development) معموله که از SQLite استفاده کنند تا صرفا ببینن که آیا ساختار داده‌هاشون درسته یا خیر.

تعریف پروژه

خب، حالا که می‌دونیم قراره از جاوا و SQLite استفاده کنیم، بیایم پروژه رو تعریف کنیم. پروژه برای من به این شکل تعریف شده بود:

برنامه‌ای بنویسید که یک نام و یک شماره تلفن از کاربر دریافت کرده و سپس آن را در یک پایگاه‌داده SQLite ذخیره کند.

برای این که پروژه رو کمی متفاوت از چیزی که خودم برای تمرین زدم کنیم، صورتش رو به این شکل تغییر میدیم :

برنامه‌ای بنویسید که یک نام، شماره تلفن و ایمیل از کاربر دریافت کرده و سپس آن را در یک پایگاه‌داده SQLite ذخیره کند.

ابزارهای مورد استفاده در این پروژه

در این پروژه، من از این ابزارها استفاده کردم:

  • جاوا نسخه ۱۳
  • محیط یکپارچه توسعه IntelliJ IDEA
  • درایور SQLite برای جاوا (لینک)

ضمنا، من از سیستم‌عامل لینوکس (در حال حاضر اوبونتو/دبیان) استفاده می‌کنم و چیزایی که در این آموزش بهشون اشاره می‌کنم عموما دستورات لینوکسی هستند. اگر ویندوزی هستید هم میتونید از WSL استفاده کنید یا دستورات مشابه پیدا کنید.

آماده‌سازی و ایجاد پروژه

پس از باز کردن IntelliJ IDEA و سپس ایجاد یک پروژه Command Line جدید، از منوی File و زیرمنوی Project Structure زبانه Dependencies را انتخاب کرده و سپس فایل jar ای که برای SQLite JDBC Driver دریافت کرده‌اید را به پروژه وارد کنید. همچنین، من با دستور زیر، یک دیتابیس خالی در پوشه‌ای در کامپیوتر خودم ایجاد کردم:

touch /home/prp-e/playground/java.sqlite3

به این شکل، من یک فایل قابل فهم برای SQLite ساخته‌ام. قدم بعدی، آشنایی نسبی با پرس‌وجوهای SQLite است.

کمی آشنایی با SQLite

مثل هر دیتابیس SQL دیگری، SQLite هم مجموعه‌ای از پرس‌وجوها اجرا می‌کنه تا به نتیجه‌ای که ما میخوایم برسه. در این بخش، اونهایی که در پروژه استفاده می‌شن رو بررسی می‌کنیم.

ساخت جدول جدید

همونطور که اول گفتیم، قراره در جدول تماسهامون، نام، تلفن و ایمیل اشخاص رو ذخیره کنیم. به همین خاطر موارد رو لحاظ می‌کنیم:

  • یک شناسه منحصر به فرد برای هرفرد که به صورت خودکار، افزایش پیدا کنه
  • اسم فرد به صورت یک رشته متنی
  • شماره فرد به صورت رشته متنی (برای شماره هایی که – یا + و … دارند)
  • ایمیل فرد به صورت رشته متنی

پس پرس‌وجوی اول ما به این شکل میشه :

CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);

در این پرس‌وجو، داریم می‌گیم که اگر جدولی به اسم contacts نبود بسازش. برای هر کاربر یک شناسه به صورت PRIMARY_KEY یا همون شناسه اولیه/منحصر به فرد درنظر بگیر که به صورت خودکار افزایش پیدا کنه. اسم، شماره و ایمیل هم به صورت متن دریافت کن اما خالی نباشن.

اضافه کردن تماس جدید

برای اضافه کردن تماس جدید، کل کاری که باید انجام بدیم اجرای این پرس و جوئه :

INSERT INTO contacts (name, number, email) VALUES ("John Doe", "1-555-123456", "john.doe@gmail.com");

در این پرس و جو میگیم که یک تماس جدید با مشخصات شخصی به نام John Doe به این پایگاه داده اضافه بشه.

پیاده‌سازی در جاوا

برای پیاده‌سازی پروژه، ما نیاز به این موارد داریم:

  • تابعی که اسم دیتابیس، پرس‌وجوی اولیه و پرس‌وجوی مورد نظر ما رو دریافت کنه
  • نوشتن برنامه‌ای که کار دریافت اطلاعات رو انجام بده

تابع دریافت اطلاعات

public static void database_init(String db_address, String init_query, String query){
        String conn = "jdbc:sqlite:/" + db_address;
        try {
            Connection connection = DriverManager.getConnection(conn);
            System.out.println("Connection established to the database.");

            Statement statement = connection.createStatement();
            statement.execute(init_query);

            System.out.println("Successfully created the table.");

            statement.execute(query);

            System.out.println("Successfully ran the query");
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }

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

در مورد Connection, Statement و try catch ها نگران نباشید. این‌ها چیزایین که توسط IntelliJ IDEA هندل میشن. فقط موقع ساخت Connection حواستون باشه که بهتون خطا میده و ازتون میپرسه که «آیا در try catch قرارش بدم؟» و شما باید تاییدش کنید.

حالا که تابع ارتباط با دیتابیس رو داریم، وقتشه که اطلاعات رو از کاربر بگیریم. این کار رو من در تابع main می‌کنم.

تابع اصلی

در تابع اصلی، لازمه که نام، تلفن و ایمیل افراد رو با پیام مناسب، دریافت کنیم. این تابع اصلی برنامه من شد:

public static void main(String[] args) {
    // write your code here
        String query = "CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);";

        Scanner name = new Scanner(System.in);
        Scanner number = new Scanner(System.in);
        Scanner email = new Scanner(System.in);

        System.out.print("Enter a name: ");
        String input_name = name.nextLine();

        System.out.print("Enter a phone number: ");
        String input_number = number.nextLine();

        System.out.print("Enter an email address:");
        String input_email = email.nextLine();

        String insertion_query = "INSERT INTO contacts (name, number, email) VALUES (\"" + input_name + "\", \"" + input_number + "\"" + ", \"" + input_email +"\")";

        database_init("/home/prp-e/playground/java.sqlite3", query, insertion_query);




    }

همونطور که می‌بینید ابتدا یک رشته به اسم query دارم که در اون توضیح دادم دقیقا میخوام چه جدولی با چه مشخصاتی برام ساخته شه. همچنین چک بشه که اگر جدول موجوده، ساخته نشه و روی همون جدول موجود داده‌های جدید وارد بشن.

بعد از اون، سه تا شیء Scanner ایجاد کردم که ورودی رو از ترمینال کاربر بخونن. پس از اون، پیام‌های مناسب رو چاپ کردم و مقداری که Scanner از شما دریافت کرده رو داخل رشته‌های جدید ریختم.

پس از اون هم یه پرس‌وجوی بزرگ ساختم و در اون تعریف کردم که چیزایی که توسط Scanner ها خونده شدند، دقیقا کجا قرار بگیرند. در نهایت، هرچه بود و نبود رو دادم به تابع database_init .

برنامه کامل

این هم کد برنامه کامل که ببینید چی به چیه:

package com.haghiri75;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class Main {

    public static void database_init(String db_address, String init_query, String query){
        String conn = "jdbc:sqlite:/" + db_address;
        try {
            Connection connection = DriverManager.getConnection(conn);
            System.out.println("Connection established to the database.");

            Statement statement = connection.createStatement();
            statement.execute(init_query);

            System.out.println("Successfully created the table.");

            statement.execute(query);

            System.out.println("Successfully ran the query");
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }


    public static void main(String[] args) {
    // write your code here
        String query = "CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);";

        Scanner name = new Scanner(System.in);
        Scanner number = new Scanner(System.in);
        Scanner email = new Scanner(System.in);

        System.out.print("Enter a name: ");
        String input_name = name.nextLine();

        System.out.print("Enter a phone number: ");
        String input_number = number.nextLine();

        System.out.print("Enter an email address:");
        String input_email = email.nextLine();

        String insertion_query = "INSERT INTO contacts (name, number, email) VALUES (\"" + input_name + "\", \"" + input_number + "\"" + ", \"" + input_email +"\")";

        database_init("/home/prp-e/playground/java.sqlite3", query, insertion_query);




    }
}

جمع‌بندی

گرچه این پروژه خیلی از مفاهیم شی‌گرایی رو در خود نداره، تا حد زیادی هم به نظر خودم کثیف نوشته شده و می‌شد از این بهتر باشه، اما پروژه خوبی برای سرگرم شدن به مدت ۲-۳ روز باشه. همچنین توضیح دوباره‌ش باعث شد که کمی کد رو تمیزتر کنم و سپس مطلب رو بنویسم.

این پروژه، برای به چالش کشیدن خیلی از توانایی‌های شما، میتونه گزینه خوبی به حساب بیاد. فلذا اگر میخواید کمی توانایی برنامه‌نویسی خودتون رو محک بزنید، توصیه می‌کنم که شما هم این پروژه رو پیاده‌سازی کنید 🙂

موفق باشید!

Share

کاپریس لینوکس نسخه ۱.۰ پایدار «اتمورا» ریلیز شد.

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

در اسفند ۹۸، دوست خوبی به نام دانیال بهزادی (که اسمی آشنا برای اهالی نرم‌افزار آزاد و همچنین دوستان لینوکسیه) با من تماس گرفت و پیشنهاد کاری رو داد. اون کار، تهیه یک توزیع لینوکس با حمایت یک شرکت بود و خب من اولش یکم نسبت بهش تردید داشتم اما بعدتر، قبول کردم و سراغ کار رفتیم. در حین این کار، من فهمیدم به یک «زمین بازی» نیاز دارم. همون پروسه‌ای که برای تولید توزیع لینوکسی که شرکت بابتش هزینه می‌کرد رو بابت یک پروژه شخصی طی کردم و هرچی به نظرم این وسط ممکن بود مشکل‌ساز شده باشه رو یه جا یادداشت می‌کردم که باگها دربیان.

کم‌کم دیدم چیزی که خودم ساختم هم کم چیزی نشده. نتیجتا، یه سری از ایده‌های خودم رو روش پیاده کردم و اسمش هم شد «کاپریس لینوکس». کاپریس، هم اسم یه مدل ماشین از شورلته هم به قطعات موسیقی که تغییرات ناگهانی رو شامل میشن اطلاق میشه. این اسم خیلی میومد به پروژه و بعدها بهتر هم فیت شد.

کم کم وسطای پروژه، هیچ پوینتی برای ادامه‌ش نداشتم. اما از طرفی هم وبسایت داشتیم براش، هم یه سری کلا بهم ملحق شده بودند که این پروژه رو به یه جایی برسونن. به همین خاطر، تصمیم گرفتم هرچی ایده‌آل برای یک توزیع لینوکسی دارم رو بریزم در کاپریس! اولین قدم، تولید این میزکار قشنگ براش بود :

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

بعد از اون، به سرم زد که کمی به BSD ها نزدیکش کنم. به همین خاطر APT که سیستم نصب بسته‌های دبیانه رو نگه داشتم، سیستم pkgsrc که یک سیستم مدیریت پورت در NetBSD عه (و تقریبا روی هر سیستم‌عامل دیگری هم امکان اجرا شدن داره، البته با کمی انگولک شدن) رو برای این توزیع پیاده‌سازی کردم.

تا اینجا همه چی خوب بود، به سرم زد که systemd هم یه جوری ازش حذف کنم! کمی تحقیق و بررسی کردم و دیدم به همین سادگی‌ها نیست و یه سری ملزومات خاص داره. اما به سرم زد که سیستم rc.d رو از همون NetBSD حداقل برای سرویس‌هایی که از طریق pkgsrc نصب میشن پیاده کنم.

و خب به همین شکل، این قضیه پیشرفته و پیشرفته‌تر شد تا رسید به کاپریسی که ۱ آگوست ۲۰۲۰ معادل ۱۰ مرداد ۱۳۹۹ منتشر شد.

لینک در وبگاه خبری اصلی

از اونجایی که احتمالا شما هم کنجکاو شدید بیشتر ازش بدونید، دیگه توضیحات اضافه رو اینجا نمی‌دم. بلکه شما رو به وبسایت خود پروژه کاپریس راهنمایی می‌کنم :

http://capricelinux.org/2020/08/01/Caprice-Linux-1.0-STABLE-release-notes.html

 

Share

به روز رسانی اوبونتو از نسخه های LTS به STS

توزیع اوبونتو، معمولا در دونسخه ارائه میشه. نسخه های «پشتیبانی طولانی مدت» یا همون LTS (مخفف Long Term Support ) که اگر اشتباه نکنم هر کدوم تا پنج سال، پشتیبانی دریافت میکنند. این پشتیبانی به معنای پشتیبانی از سمت کنونیکال (شرکت سازنده این توزیع)، دریافت آپدیت های امنیتی و همچنین به روز شدن مستندات توزیع است.

نسخه های STS که طبق روتین ارائه اوبونتو هر شش ماه یه بار میان، قبلا دو سال پشتیبانی می‌شدند ولی مثل این که الان این پشتیبانی کمتر شده و همون شش ماه (یا یک سال، دقیقا نمیدونم و یادم نیست) پشتیبانی رو دریافت میکنن. این نسخه ها به قول معروف «روی لبه تکنولوژی حرکت میکنند» و معمولا تکنولوژی های جدیدی رو در خودشون جای دادن.

هر کدوم از این نسخه ها، مزایای خودش رو داره. خیلی از افراد رو دیدم که با هر آپدیتی، سریعا سیستم عامل خودشون رو آپدیت میکنند و خیلی ها هم ترجیح میدند دو سال یک بار، نسخه های LTS رو آپدیت کنند و یا حتی کل پنج سالی که برای LTS ها پشتیبانی در نظر گرفته شده، روی اون بمونن. اما برگردیم به دسته اول!

فرض کنیم شما آخرین اوبونتوی LTS (در حال حاضر ۱۸.۰۴ ) رو نصب کردید و میخواهید به STS جدید (در حال حاضر ۱۹.۰۴) به‌روز رسانی کنید. برای این کار، نیاز به چند مرحله داریم. اول لازمه که update-manager رو نصب کنیم :

sudo apt install update-manager-core

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

گام دوم، اینه که به آپدیت منیجر، بگیم که به جای lts در نسخه های normal برامون دنبال ریلیز جدید بگرده. فقط کافیه این فایل رو با یک ویرایشگر متن باز کنیم (البته ترجیحا ویرایشگرهای خط فرمان؛ چون دسترسی ریشه نیاز داریم) :

/etc/update-manager/release-upgrades

سپس در این فایل، شما احتمالا این خط رو می‌بینید :

Prompt=lts

با تغییر مقدار متغیر prompt به normal ، شما به آپدیت منیجر گفتید که در نسخه های STS به دنبال ریلیز جدید بگرده. بعد از این که عبارت lts رو با normal جایگزین کردید، کافیه فایل رو ذخیره کرده، ببندید و در ترمینال تایپ کنید :

do-release-upgrade

و جایی هم نیاز به پسورد داشته باشید، این دستور ازتون دریافتش خواهد کرد.

این راه حلی بود که خودم دقیقا استفاده کردم برای آپدیت به ۱۹.۰۴. نمیدونم قبلتر کسی در وب فارسی توضیحش داده یا نه، ولی خب امیدوارم که به کارتون بیاد 🙂

Share

چگونه در سطح سخت افزار، عدد تصادفی تولید کنیم؟

تولید عدد تصادفی، یکی از کارهاییه که در برنامه نویسی بسیار نیازش داریم. برای چه منظورهایی؟ برای مثال فرض کنید میخواهیم یک شبکه عصبی طراحی کنیم و وزن‌های ما باید تصادفی باشن. به همین خاطر، ما از عدد های تصادفی برای تولید وزن استفاده میکنیم. در سطح نرم افزار، تولید عدد تصادفی بسیار آسونه. مثلا در پایتون ما میتونیم به این شکل عدد تصادفی تولید کنیم (راهی غیر از numpy هم هست، ولی من اکثرا از این روش استفاده میکنم) :

from numpy import random 

random.seed(1) 

print(random.random((1, 1)))

ولی در سطح سخت‌افزار، کار کمی پیچیده تر میشه. در اینجا قصد دارم یک مدار ساده بسازم که دقیقا چنین کاری رو انجام میده. البته به این مدار گفته میشه Pseudo Random Number Generator چون نتایج، تصادفی تصادفی هم نیستند ولی برای کارهایی که به عدد تصادفی نیاز داره، خوبن.

خب، طراحی مدار ما به شکل زیره :

ما اومدیم چهار فلیپ فلاپ D رو به هم متصل کردیم. سپس، دو بیت کم ارزش در اتصال این زنجیره را با یک XNOR با هم مقایسه کردیم و یک پالس ساعت هم به مدار وارد کردیم.

وقتی که دو بیت کم ارزش صفر باشن، خروجی XNOR ما یک میشه. یعنی Q در فلیپ فلاپ پر ارزش (سمت چپ ترین)، برابر با یک خواهد شد. در پالس بعدی این اتفاق برای فلیپ فلاپ بعدی میفته، این اتفاق تا جایی میفته که نتیجه مقایسه، صفر میشه و فلیپ فلاپ پر ارزش مقدارش تغییر میکنه، به این شکل، دقیقا ترتیب اعدادی که در این Ring Counter داریم به هم میریزه و اعداد «شبه‌تصادفی» تولید میشن.

این هم از شبیه‌سازی این مدار :

همونطور که در ویدئو مشخصه، داره به صورت رندم عددهای چهاربیتی تولید میکنه.

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

Share

راهنمای یک صفحه‌ای برای علاقمندان به رشته کامپیوتر

مدتهاست که با دوستان مختلف، روی نوشتن مطالبی پیرامون رشته مهندسی کامپیوتر بحث می‌کنیم. این بحثها شامل ایرادات روتین بچه‌های مهندسی کامپیوتر تا کار کردن روی یک پروژه نه چندان بزرگ (ولی پرچالش!) میشه. از اونجایی که تازه هم کنکور گذشته و بچه ها کمی آزاد شدن، ولی ممکنه برای انتخاب رشته دچار تردید بشن؛ وقت خوبی بود که مطالبی در مورد ماهیت این رشته نوشته بشه. مطالبی که مینویسم، حاصل مطالعاتیه که در این چند سال داشتم. سعی میکنم کمی تاریخ تعریف کنم، کمی از علوم کامپیوتر بگم و در نهایت هم کمی از چیستی و ماهیت خود خود کامپیوتر (نه رشته).

کمی تاریخ

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

فلسفه و ریاضیات

فلاسفه و ریاضی دانان، افرادی بودن که به دنبال پاسخ بودن. البته فلاسفه، پرسشگران قهارتری هم بودن و گاهی، سوالاتی مطرح کردند و ریاضیدانان، اون سوالات رو پاسخ دادن. حالا با توجه به این که کامپیوتر یک «ابزار حل مساله‌»س، میشه گفت هر دو گروه به شدت درش دخیل بودن.گاهی هم فلاسفه‌ای که روی علوم کامپیوتر تاثیر داشتند، ریاضی دان هم بودن. نمونه‌ش هم «محمد بن موسی خوارزمی» دانشمند پارسی‌گو.

خوارزمی، شاید اولین کسی بود که «تفکر رایانش» رو ابداع کرد. در کتاب معروفی به نام «جبر و مقابله» به حل معادلات جبری پرداخته و راه حل هاش، عموما مرحله مرحله و شفافن. به همین خاطر هم وقتی این روش حل مساله به اروپا میرسه، اروپایی ها بخاطر «الخوارزمی» (اسم ایشون) ، که در لاتین «الگوریتمی» گفته می‌شده، روش حل مساله رو «الگوریتم» اسم گذاشتند. چیزی که هنوز که هنوزه، داره استفاده میشه.

البته، کار خوارزمی نظام بخشیدن و سازمان دادن به علوم و فنونی بوده که در زمان خودش، مطرح می‌شده. در واقع، از کشف صفر توسط هندی ها تا قضایای که امثال تالس و فیثاغورث پایه گذاشتن، همه در نوشته شدن «جبر و مقابله» و ایجاد تفکر سیستماتیک برای حل مساله، دخیل بودن.

منطق

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

منطقی که ارسطو بنیان گذاشته، یک منطق صفر و یکی به حساب میاد. بذارید اینطوری بگم؛ با منطق ارسطویی میشه اینطور گفت :

علی از احمد قدبلندتره. احمد از حسن قد بلند تر. پس علی از حسن هم قدبلندتره

و در این مورد، منطق ارسطویی کاملا کار میکنه. مثلا ریاضیاتیش میشه :

اگر x آنگاه y ، اگر y آنگاه p -> اگر x آنگاه p

و این بیان رو ما اصولا در نوعی از ریاضیات به نام «ریاضیات گسسته» یاد می‌گیریم. چیزی که پایه و اساس علوم و مهندسی کامپیوتر امروزیه. اما، این فقط کافی نیست؛ منطق در یک محیط خاص کار میکنه که ما اعدادی جز صفر و یک نداریم! پس نیاز به نوعی از محاسبه و جبر داریم که برای فقط صفر و یک، کار کنه و کافی باشه. چیزی به اسم «جبر بول»

آقایی که در تصویر می‌بینید، جورج بول، ریاضی‌دان و فیلسوف انگلیسیه که با پایه گذاری جبر صفر و یکی بر مبنای «صحیح و غلط» خودش، علوم کامپیوتر رو شدید تسریع کرد. در سده نوزدهم خیلی چیزا ساخته شدن و اکثرا هم، بر پایه همین «بودن یا نبودن» آقای بول کار میکردن. اما اشتباهاتی هم در این میان رخ داده که حالا بهش میرسیم!

وقتی همه چیز مکانیکی شد

 

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

آقایی که در تصویر می‌بینید «چارلز بابیج» یک ریاضی‌دان و مهندس انگلیسی بود. ایشون ایده «موتور تحلیلی» رو مطرح کرد که چیزی بود شبیه کامپیوترهای امروز. برنامه پذیر و قابلیت حل تعداد زیادی مساله در زمانی کم. اما، کار ایشون مشکلاتی داشت. ایشون سعی داشت همه چیز رو مکانیکی پیاده کنه و زمانی که این ایده رو مطرح کرد ماشین های مکانیکی هنوز اونقدر پیشرفته نبودن. و مشکل دوم رو بالاتر اشاره کردم، ایشون مدعی بوده که بدون جبر بول هم میتونه کامپیوتر رو پیاده کنه و کامپیوتری بسازه که با مبنای ده کار کنه (چیزی که هنوز هم نشده 🙂 ) .

اما ماشین های مکانیکی کم کم به سمت جبر بول و محاسبات آماری رفتن. یک بار دیگه این تصویر رو با هم ببینیم:

این تصویر، تصویری از یک ماشین «شرط بندی» است که در نیوزلند نصب شده بوده. عملکرد مکانیکی برای محاسبات آماری مربوط به شرط بندی روی مسابقه اسبها داشته.

اما مکانیک کافی نبود، لازم بود اما کافی نبود. پس به عصر «الکترومکانیک» باید سفری کوتاه داشته باشیم!

همه چیز از یک رله شروع شد

رله، قطعه الکتریکیه که میتونه مشابه یک کلید عمل کنه. در واقع اعمال ولتاژ به یک قسمتش، میتونه قطع و وصل شدن جریان الکتریکی در یک قسمت دیگر مدار رو تضمین و کنترل کنه (به این شکل ما مثلا میتونیم با استفاده از اینترنت، یک لامپ رو خاموش روشن کنیم!). در اون زمان، به فکر یه مهندس خوش ذوق آلمانی به اسم «کانراد تسوزه» زد که جبر بول رو با رله پیاده کنه. تسوزه چند تا پیاده سازی داشت ولی معروفترینشون این بود :

کامپیوتر Z4 آلمانی که در دهه ۳۰ ساخته شد و خیلی هم به کمک ارتش آلمان در جنگ دوم جهانی اومد. اما مطمئنا یک نابغه خوش ذوق دیگر در طرف انگلیسی وجود داره که بتونه از ساز و کار این ماشین، سردربیاره!

قبل از این که به اونطرف قضیه بپردازیم، این ماشین به شکل امروزی تونست برنامه اجرا کنه و زبان برنامه نویسی خاص خودش رو داشت. مجهز به سیستم ذخیره و بازیابی «پانچ کارد» بود و خیلی از مفاهیم امروزی رو در خودش داشت. اما هنوز نمیتونست «کامپیوتر» کاملی باشه چون خیلی مفاهیم رو نتونست پیاده سازی کنه، مهم تر از همه، شدیدا وابسته به عامل انسانی بود.

شروع بازی تقلید!

موقعی که کشورهای مختلف درگیر جنگ دوم بودن، اکثرا پیامهاشون رو رمزنگاری می‌کردن و شکستن رمزها، واقعا یک نابغه می‌طلبید. یک نابغه خوش ذوق که بتونه قهرمان جنگی باشه و رمز آلمانها رو بشکنه و متفقین رو، پیروز میدان کنه!

آقایی که در تصویر می‌بینید «آلن تورینگ» انگلیسی، این کار رو کرد. رمز آلمانیها موسوم به «انیگما» رو شکست و به این ترتیب قهرمان جنگی شد. اما کارش به همینجا ختم نشد و در دهه ۵۰ میلادی ایده «تفکر در رایانه» و «هوش مصنوعی» رو مطرح کرد که تا امروز هم مطالعه روی این موضوعات، ادامه داره. این شخص به معنای واقعی، نابغه و خوش ذوق بوده.

ترانزیستور و عصر سیلیکون

خب، این هم از فصل آخر تاریخ کامپیوتر. در اواخر دهه ۴۰ ، کامپیوترها یک دفعه رشد کردند. کشف ترانزیستور باعث شد مدارات الکتریکی و الکترونیکی مورد نیاز برای ساخت کامپیوتر بتونن روی یک سطح چند سانتی متری از سیلیکون خلاصه بشن. قطعاتی با کاربرد بالاتر ساخته بشن. عصر سیلیکون مصادف بود با حضور امثال دنیس ریچی و کن تامپسون و مفاهیمی مثل «سیستم عامل» (توضیح این بخش از تاریخ خودش یک پست جدا میطلبه پس شاکی نباشید از من لطفا!) مطرح بشن و رشد نرم افزاری در این حد، باعث شد که اصلا سرعت رشد یک شکل دیگری به خودش بگیره!

کامپیوتر چیست؟ کامپیوتر کیست؟

شاید باورتون نشه ولی قبل از ظهور ماشین های محاسبه گر، کامپیوتر یک عنوان شغلی بوده برای کسانی که محاسبات پیچیده رو انجام میدادن (و طوری که در موردشون مطالعه کردم، ظاهرا حق پرسش در مورد این که این محاسبه رو چرا دارن انجام میدن نداشتن) و بخش جالبتر این بوده که عموما «کامپیوتر»ها رو در سازمانها، خانمها تشکیل میدادن (البته اولین برنامه نویس جهان هم یک خانم به اسم ایدا لاولس بوده که در تصویر زیر می‌بیندشون).

البته، اونقدری نمی‌گذره که «علوم کامپیوتر» مطرح میشه. بعنوان علم مطالعه و پردازش داده. و این پدیده، همزمان بوده با پدیدار شدن کامپیوترهای به معنای امروزی. پس بیشتر اپراتور و برنامه نویس تربیت می‌کردند.

در تصویر بالا هم، عکسی از اپراتورهای کامپیوتر انیاک (در امریکا) رو می‌بینید که هم باید به نرم افزار مسلط می‌بودن و هم سخت افزارش.

اما به طور کل، کامپیوتر امروزه چی تعریف میشه؟ کامپیوتر یعنی وسیله‌ای برای پردازش داده و استفاده از اون داده در علم. ما داده های مختلفی داریم که کامپیوتر میتونه برای ما پردازشش کنه و نتیجه اون پردازش رو در هر شکلی به ما بده (یک نمودار، روشن و خاموش شدن یک دستگاه خاص یا حتی یادگیری و تکرار یک عمل از روی همون داده ها). پس، تا اینجا هم تا حد زیادی تاریخ کامپیوتر رو تونستیم بفهمیم، هم تعریفش رو. شاید براتون جالب باشه که اصلا کامپیوتر ها چطوری هم ساخته میشن!

کامپیوتر چطور داده رو پردازش میکنه؟

برگردیم به همون جبر بول. ما یه سری وسیله (یا بهتر بگم نمایش الکترونیکی!) از عملیات بولی داریم که بهشون میگن «دروازه منطقی» یا همون گیت. گیتها به این شکل هستند :

هر کدوم از اینها میتونن یکی از توابع بولین رو پیاده کنن. حالا، ما اگر اینها رو کنار هم بچینیم میتونیم بخش بزرگی از محاسبات رو به سادگی انجام بدیم. مثلا این مداری که من ساختم رو ببینید :

این مداریه که یک عدد BCD (که نوعی رمزگذاری در کامپیوتره) رو دریافت میکنه، به صورت دهدهی (دسیمال، مبنای ده) در خروجی قرار میده. حالا ما میتونیم اونطرف با یک Encoder این مقادیر رو دوباره به BCD یا هر فرمت دیگری تبدیل کنیم. در واقع کاری که ما انجام دادیم همون پردازش داده‌س. حالا هر قسمتی رو میشه یک بلاک در نظر گرفت و کنار هم قرار داد تا به چنین چیزی رسید :

مداری که در بالا طراحی کردم، یک واحد محاسبه و منطق برای یک کامپیوتر هشت بیتی بود (لینک) و این واحد، همونجاییه که داده پردازش میشه. البته واحد کنترل و حافظه هم در کامپیوتر داریم که برای کنترل پروسه پردازش و ذخیره داده پردازش شده ازشون استفاده می‌کنیم!

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

Share