سرور مجازی

۲۷ مطلب با کلمه‌ی کلیدی «سرور مجازی» ثبت شده است

  • ۰
  • ۰

نحوه نصب متابیس در اوبونتو 20.04 با داکر

ورود به سایت

معرفی

Metabase یک ابزار مبتنی بر جاوا منبع باز هوش تجاری (BI) است. این می تواند به تعدادی پایگاه داده مختلف متصل شود و یک ابزار سازنده سوال دارد که می تواند پیچیدگی پرس و جوهای بزرگ SQL را پنهان کند.

در این آموزش شما Metabase را با استفاده از Docker Compose نصب می‌کنید، سپس Nginx را نصب می‌کنید تا به عنوان یک پروکسی معکوس برای سایت متابیس شما عمل کند. سپس، اتصالات HTTPS ایمن را با استفاده از Certbot برای دانلود و پیکربندی یک گواهی TLS از Let’s Encrypt Certificate Authority فعال می کنید. در نهایت، Metabase را پیکربندی می‌کنید و برخی از داده‌های نمونه را بارگیری می‌کنید تا بتوانید سؤالات و داشبوردهای BI خود را بسازید.

پیش نیازها

برای تکمیل این آموزش شما نیاز دارید:

یک سرور اوبونتو 20.04 با 2 یا بیشتر CPU، یک کاربر غیر ریشه با دسترسی sudo و یک فایروال. برای تنظیم این، آموزش راه اندازی سرور اولیه ما با اوبونتو 20.04 را دنبال کنید.
داکر نصب شده است. مراحل 1 و 2 نحوه نصب و استفاده از Docker در اوبونتو 20.04 را دنبال کنید تا آن را نصب کنید و کاربر غیر روت خود را پیکربندی کنید تا بتواند دستورات docker را اجرا کند.

در نهایت، برای فعال کردن TLS به یک نام دامنه نیاز دارید که به آدرس IP عمومی سرور شما اشاره شده باشد. این باید چیزی شبیه example.com یا metabase.example.com باشد. اگر از DigitalOcean استفاده می کنید، لطفاً برای کسب اطلاعات در مورد ایجاد منابع دامنه در کنترل پنل خود، به Start سریع DNS ما مراجعه کنید.

هنگامی که تمام پیش نیازها را آماده کردید، به مرحله 1 بروید، جایی که بسته docker-compose را نصب خواهید کرد.

مرحله 1 – نصب Docker Compose

برای نصب ابزار خط فرمان docker-compose، ابتدا لیست بسته خود را بازخوانی کنید:

sudo apt update

سپس بسته را با استفاده از apt نصب کنید:

sudo apt install docker-compose

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

docker-compose –version

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

 

Output

docker-compose version 1.25.0, build unknown
docker-py version: 4.1.0
CPython version: 3.8.10

هنگامی که تأیید کردید که Docker Compose روی سرور شما نصب شده است، از آن برای پیکربندی و راه اندازی Metabase در مرحله بعدی این آموزش استفاده خواهید کرد.

مرحله 2 – اجرای Metabase با Docker Compose

برای شروع ایجاد محفظه Metabase خود، دایرکتوری به نام metabase را در فهرست اصلی خود ایجاد کنید تا فایل هایی را که در این آموزش ایجاد خواهید کرد ذخیره کنید. شما از این دایرکتوری برای ذخیره تمام فایل هایی که برای اجرای Metabase نیاز دارید استفاده خواهید کرد.

برای ایجاد دایرکتوری دستور زیر را اجرا کنید:

mkdir ~/metabase

سپس در آن حرکت کنید:

cd ~/metabase

اکنون یک فایل YAML خالی جدید به نام docker-compose.yml را با استفاده از nano یا ویرایشگر دلخواه خود باز کنید:

nano docker-compose.yml

شما از این فایل با دستور docker-compose برای راه اندازی ظرف Metabase خود استفاده خواهید کرد. خطوط زیر را به فایل اضافه کنید:

docker-compose.yml

version: '3'
services:
  metabase:
    image: metabase/metabase:latest
    ports:
      - "3000:3000"
    volumes:
      - data:/metabase

volumes:
  data:

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

پس از اتمام ویرایش فایل را ذخیره کرده و از آن خارج شوید. اگر از نانو استفاده می کنید، CTRL+O و سپس RETURN را برای ذخیره و سپس CTRL+X را برای خروج فشار دهید.

اکنون آماده هستید تا ظرف متابیس را با دستور docker-compose راه اندازی کنید:

docker-compose up -d

فرمان فرعی up به docker-compose می‌گوید که ظرف و حجم(های) و شبکه(های) مرتبط را که در فایل docker-compose.yml شما تعریف شده‌اند، راه اندازی کند. پرچم -d (که مخفف “daemonize” است) به docker-compose می‌گوید که کانتینر را در پس‌زمینه اجرا کند تا فرمان ترمینال شما را نگیرد. docker-compose زمانی که تصویر Docker مورد نیاز را دانلود می‌کند و سپس کانتینر را راه‌اندازی می‌کند، خروجی مختصری را چاپ می‌کند:

 

Output

Creating network "metabase_default" with the default driver
Creating volume "metabase_data" with default driver
Pulling metabase (metabase/metabase:latest)...
latest: Pulling from metabase/metabase
. . .

docker-compose stop

وقتی این کار انجام شد، Metabase باید در حال اجرا باشد. می توانید با واکشی صفحه اصلی با استفاده از دستور curl آزمایش کنید که یک وب سرور در 127.0.0.1:3000 اجرا می شود:

curl –head http://localhost:3000

با این کار فقط سرصفحه های HTTP از پاسخ چاپ می شود:

 

Output

HTTP/1.1 200 OK
Date: Tue, 15 Mar 2022 19:26:22 GMT
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Last-Modified: Tue, 15 Mar 2022 19:26:22 GMT
Strict-Transport-Security: max-age=31536000
Set-Cookie: metabase.DEVICE=3525ed6d-13e0-4ad0-8fdb-f1bc426706dc;HttpOnly;Path=/;Expires=Sat, 15 Mar 2042 19:26:22 GMT;SameSite=Lax
X-Permitted-Cross-Domain-Policies: none
Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; script-src 'self' 'unsafe-eval' https://maps.google.com https://apis.google.com https://*.googleapis.com *.gstatic.com https://www.google-analytics.com   'sha256-lMAh4yjVuDkQ9NqkK4H+YHUga+anpFs5JAuj/uZh0Rs=' 'sha256-ib2/2v5zC6gGM6Ety7iYgBUvpy/caRX9xV/pzzV7hf0=' 'sha256-JJa56hyDfUbgNfq+0nq6Qs866JKgZ/+qCq2pkDJED8k='; child-src 'self' https://accounts.google.com; style-src 'self' 'unsafe-inline'; font-src 'self' ; img-src * 'self' data:; connect-src 'self' metabase.us10.list-manage.com www.google-analytics.com https://sp.metabase.com ; manifest-src 'self';  frame-ancestors 'none';
Content-Type: text/html;charset=utf-8
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

پاسخ OK 200 به این معنی است که یک برنامه در پورت 3000 پاسخ می دهد. هدرهای Set-Cookie و Server برجسته شده تأیید می کنند که برنامه Metabase در سرور وب Jetty اجرا می شود.

سپس Nginx را برای پراکسی کردن ترافیک عمومی به کانتینر Metabase راه‌اندازی می‌کنیم.

مرحله 3 – نصب و پیکربندی Nginx

قرار دادن یک وب سرور مانند Nginx در مقابل سرور Metabase شما می‌تواند عملکرد را با بارگذاری ذخیره‌سازی، فشرده‌سازی و سرویس فایل استاتیک برای فرآیندی کارآمدتر بهبود بخشد. ما قصد داریم Nginx را نصب کنیم و آن را به گونه ای پیکربندی کنیم که درخواست های پراکسی را به Metabase معکوس کند، به این معنی که از رسیدگی به درخواست های کاربران شما به Metabase و بازگشت مجدد مراقبت می کند. استفاده از فرآیند Nginx غیر کانتینری اضافه کردن گواهینامه‌های Let’s Encrypt TLS را در مرحله بعدی آسان‌تر می‌کند.

ابتدا لیست بسته خود را بازخوانی کنید، سپس Nginx را با استفاده از apt نصب کنید:

sudo apt install nginx

با استفاده از نمایه برنامه Nginx Full UFW، ترافیک عمومی به پورت های 80 و 443 (HTTP و HTTPS) را مجاز کنید:

sudo ufw allow “Nginx Full”

 

Output

Rule added
Rule added (v6)

در مرحله بعد، یک فایل پیکربندی جدید Nginx را در پوشه /etc/nginx/sites-available باز کنید. ما سایت خود را metabase.conf می نامیم اما می توانید از نام دیگری استفاده کنید:

sudo nano /etc/nginx/sites-available/metabase.conf

موارد زیر را در فایل پیکربندی جدید جای‌گذاری کنید، مطمئن شوید که your_domain_here را با دامنه‌ای که پیکربندی کرده‌اید برای اشاره به سرور متابیس خود جایگزین کنید. برای مثال باید چیزی شبیه metabase.example.com باشد:

/etc/nginx/sites-available/metabase.conf

server {
    listen       80;
    listen       [::]:80;
    server_name  your_domain_here;

    access_log  /var/log/nginx/metabase.access.log;
    error_log   /var/log/nginx/metabase.error.log;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Proto https;
      proxy_pass http://localhost:3000;
  }
}

این پیکربندی فعلاً فقط HTTP است، زیرا به Certbot اجازه می‌دهیم تا در مرحله بعدی پیکربندی TLS را انجام دهد. بقیه فایل پیکربندی مکان های ورود به سیستم را تنظیم می کند و سپس تمام ترافیک و همچنین برخی از هدرهای پراکسی مهم را به همراه http://localhost:3000، ظرف Metabase که در مرحله قبل راه اندازی کردیم، ارسال می کند.

فایل را ذخیره کرده و ببندید، سپس با پیوند دادن آن به /etc/nginx/sites-enabled/ پیکربندی را فعال کنید:

sudo ln -s /etc/nginx/sites-available/metabase.conf /etc/nginx/sites-enabled/

از nginx -t برای بررسی درست بودن نحو فایل پیکربندی استفاده کنید:

sudo nginx -t

 

Output

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

و در نهایت سرویس nginx را با پیکربندی جدید بارگیری مجدد کنید:

sudo systemctl reload nginx.service

سایت متابیس شما اکنون باید با HTTP ساده در دسترس باشد. http://your_domain_here را بارگیری کنید (ممکن است مجبور شوید از طریق یک هشدار امنیتی کلیک کنید) و به شکل زیر خواهد بود:

اکنون که سایت خود را از طریق HTTP راه‌اندازی کرده‌اید، زمان آن رسیده است که اتصال را با گواهی‌های Certbot و Let’s Encrypt ایمن کنید. شما باید این کار را قبل از انجام مراحل راه اندازی مبتنی بر وب متابیس انجام دهید.

مرحله 4 – نصب Certbot و راه‌اندازی گواهی‌های TLS

به لطف Certbot و مجوز مجوز رایگان Let’s Encrypt، افزودن رمزگذاری TLS به برنامه Metabase شما تنها دو دستور را می‌گیرد.

ابتدا Certbot و افزونه Nginx آن را نصب کنید:

sudo apt install certbot python3-certbot-nginx

سپس، certbot را در حالت –nginx اجرا کنید و همان دامنه ای را که در دستورالعمل پیکربندی Nginx server_name استفاده کرده اید، مشخص کنید:

sudo certbot –nginx -d your_domain_here

از شما خواسته می شود با شرایط خدمات Let’s Encrypt موافقت کنید و یک آدرس ایمیل وارد کنید.

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

پس از آن، Let’s Encrypt درخواست شما را تایید می کند و Certbot گواهی شما را دانلود می کند:

 

Output

Congratulations! You have successfully enabled https://metabase.example.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=metabase.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/metabase.example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/metabase.example.com/privkey.pem
   Your cert will expire on 2022-05-09. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Certbot به طور خودکار Nginx را با پیکربندی و گواهی های جدید بارگیری می کند. سایت خود را مجدداً در مرورگر خود بارگیری کنید و اگر گزینه تغییر مسیر را انتخاب کنید، باید به طور خودکار شما را به HTTPS تغییر دهد.

سایت شما اکنون ایمن است و ادامه مراحل راه اندازی مبتنی بر وب بی خطر است.

مرحله 5 – راه اندازی متابیس

به مرورگر وب خود برگردید، صفحه را دوباره بارگیری کنید. اکنون باید صفحه پیکربندی پایگاه داده Metabase را از طریق یک اتصال امن https:// باز کنید. اکنون می توانید با کلیک روی دکمه Let’s get start، فرآیند پیکربندی را تکمیل کنید.

از شما خواسته می شود که جزئیات زیر را وارد کنید:

زبان مورد علاقه شما چیست؟ اگر زبان شما در لیست است، آن را انتخاب کنید و در تصویر زیر روی Next کلیک کنید:

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

اطلاعات خود را اضافه کنید: روی گزینه I’ll add my data later در پایین صفحه کلیک کنید

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

همه چیز آماده اید! اگر می‌خواهید به‌روزرسانی‌های پروژه Metabase را دریافت کنید، آدرس ایمیل خود را اضافه کنید، در غیر این صورت می‌توانید این قسمت را نادیده بگیرید.

در نهایت روی دکمه Take me to Metabase کلیک کنید. به صفحه‌ای می‌رسید که روی آن «سلام، سامی» در بالا آمده است، با مجموعه‌ای از اشعه‌های ایکس از پیش پیکربندی‌شده که می‌توانید روی آن کلیک کنید تا داده‌های نمونه‌ای را که بارگیری کرده‌اید بررسی کنید.

برای مشاهده جزئیات جدول در متابیس روی هر X-Ray کلیک کنید. می‌توانید از کنترل‌های صفحه X-Ray برای فیلتر کردن داده‌ها یا کشف فیلدها و جداول پایگاه داده مرتبط استفاده کنید.

وقتی آماده هستید که سؤال خود را ایجاد کنید (این اصطلاحی است که Metabase برای توصیف یک پرس و جو استفاده می کند)، روی نماد Browse data grid در سمت راست بالای صفحه خود کلیک کنید. روی کاشی Sample Database کلیک کنید و سپس روی جدولی از لیست کلیک کنید. در این مثال از جدول Reviews استفاده می کنیم.

صفحه نمایش شما شبیه موارد زیر خواهد بود:

اکنون بر روی دکمه خلاصه در سمت راست بالای صفحه خود کلیک کنید و قسمت Summarize by را به Average of Rating تغییر دهید. Metabase این مقدار را بر اساس داده های جدول در قسمت Rating محاسبه می کند. همچنین گروه با فیلد را به Created At تغییر دهید، زیرا این فیلد به Metabase اجازه می‌دهد تا میانگین رتبه‌بندی محصول در هر ماه را در تمام محصولات و رتبه‌بندی‌های نمونه محاسبه کند.

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

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

نتیجه

در این آموزش، ابزار Metabase BI را با استفاده از Docker Compose راه‌اندازی کردید، سپس یک پروکسی معکوس Nginx راه‌اندازی کردید و آن را با استفاده از گواهی‌های Let’s Encrypt TLS ایمن کردید. شما همچنین چند نمونه از داده‌ها را اضافه کردید، و با ایجاد سؤالات خود در Metabase آزمایش کردید تا داده‌ها را پرس و جو کنید.

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

برچسب‌ها:Metabase یک ابزار مبتنی بر جاوااتصال به سرور مجازی لینوکساوبونتو 20.04 با داکرخرید سرور مجازیخرید سرور مجازی فرانسهسرور مجازینحوه نصب متابیسنصب Certbotنصب Docker Composeنصب و پیکربندی Nginxهوش تجاری (BI)

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه تنظیم سهمیه های سیستم فایل در اوبونتو 20.04

ورود به سایت

معرفی

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

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

پیش نیازها

این آموزش فرض می‌کند که شما وارد سرور اوبونتو 20.04 شده‌اید، با یک کاربر غیر ریشه و دارای sudo فعال، همانطور که در راه‌اندازی سرور اولیه با اوبونتو 20.04 توضیح داده شده است. تکنیک‌های این آموزش معمولاً باید روی توزیع‌های لینوکس به غیر از اوبونتو کار کنند، اما ممکن است نیاز به تطبیق داشته باشند.

مرحله 1 – نصب Quota Tools

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

sudo apt update
sudo apt install quota

با اجرای دستور quota و درخواست اطلاعات نسخه آن، می توانید تأیید کنید که ابزارها نصب شده اند:

quota –version

 

Output

Quota utilities version 4.05.
. . .

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

بعد مطمئن شوید که ماژول های هسته مناسب برای نظارت بر سهمیه ها را دارید.

مرحله 2 – ماژول Quota Kernel را نصب کنید

اگر روی یک سرور مجازی مبتنی بر ابر هستید، نصب پیش‌فرض لینوکس اوبونتو ممکن است ماژول‌های هسته مورد نیاز برای پشتیبانی از مدیریت سهمیه را نداشته باشد. برای بررسی، از find برای جستجوی ماژول های quota_v1 و quota_v2 در فهرست /lib/modules/… استفاده می کنید:

find /lib/modules/ -type f -name ‘*quota_v*.ko*’

 

Output

/lib/modules/5.4.0-99-generic/kernel/fs/quota/quota_v2.ko
/lib/modules/5.4.0-99-generic/kernel/fs/quota/quota_v1.ko

نسخه هسته خود را – که در مسیرهای فایل بالا مشخص شده است – یادداشت کنید زیرا در مرحله بعد به آن نیاز خواهید داشت. احتمالاً متفاوت خواهد بود، اما تا زمانی که دو ماژول در لیست هستند، همه چیز آماده است و می توانید بقیه این مرحله را رد کنید.

اگر هیچ خروجی از دستور بالا دریافت نکردید، بسته linux-image-extra-virtual را نصب کنید:

sudo apt install linux-image-extra-virtual

مرحله 3 – گزینه های نصب فایل سیستم را به روز کنید

برای فعال کردن سهمیه ها در یک فایل سیستم خاص، باید آن را با چند گزینه مرتبط با سهمیه مشخص شده نصب کنید. می توانید این کار را با به روز رسانی ورودی سیستم فایل در فایل پیکربندی /etc/fstab انجام دهید. آن فایل nano یا ویرایشگر متن دلخواه خود را باز کنید:

sudo nano /etc/fstab

محتویات این فایل مشابه موارد زیر خواهد بود:

/etc/fstab

LABEL=cloudimg-rootfs   /        ext4   defaults        0 0
LABEL=UEFI      /boot/efi       vfat    defaults        0 0

این فایل fstab از یک سرور مجازی است. یک رایانه رومیزی یا لپ تاپ احتمالاً fstab کمی متفاوت خواهد داشت، اما در بیشتر موارد شما یک فایل سیستم / یا root خواهید داشت که تمام فضای دیسک شما را نشان می دهد.

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

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

/etc/fstab

LABEL=cloudimg-rootfs   /        ext4   usrquota,grpquota        0 0
. . .

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

برای اعمال گزینه های جدید، فایل سیستم را مجدداً نصب کنید:

sudo mount -o remount /

در اینجا از پرچم -o برای عبور از گزینه remount استفاده می شود.

 

Output

mount: /etc/fstab: parse error

می توانید با مشاهده فایل /proc/mounts بررسی کنید که از گزینه های جدید برای نصب فایل سیستم استفاده شده است. در اینجا، از grep استفاده کنید تا فقط ورودی سیستم فایل ریشه در آن فایل را نشان دهید:

cat /proc/mounts | grep ‘ / ‘

 

Output

/dev/vda1 / ext4 rw,relatime,quota,usrquota,grpquota 0 0

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

مرحله 4 – فعال کردن سهمیه ها

قبل از اینکه در نهایت سیستم سهمیه را روشن کنید، باید یک بار دستور quotacheck را به صورت دستی اجرا کنید:

sudo quotacheck -ugm /

این دستور فایل های /aquota.user و /aquota.group را ایجاد می کند. این فایل‌ها حاوی اطلاعاتی درباره محدودیت‌ها و استفاده از سیستم فایل هستند و قبل از روشن کردن نظارت بر سهمیه باید وجود داشته باشند. پارامترهای quotacheck مورد استفاده عبارتند از:

u: مشخص می کند که یک فایل سهمیه مبتنی بر کاربر باید ایجاد شود
g: نشان می دهد که یک فایل سهمیه مبتنی بر گروه باید ایجاد شود
m: نصب مجدد فایل سیستم را به عنوان فقط خواندنی در حین انجام محاسبه اولیه سهمیه ها غیرفعال می کند. نصب مجدد فایل سیستم به‌عنوان فقط خواندنی، در صورتی که کاربر به طور فعال فایل‌ها را در طول فرآیند ذخیره کند، نتایج دقیق‌تری به دست می‌دهد، اما در این راه‌اندازی اولیه ضروری نیست.
اگر نیازی به فعال کردن سهمیه‌های مبتنی بر کاربر یا گروه ندارید، می‌توانید گزینه quotacheck مربوطه را کنار بگذارید.

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

ls /

 

Output

aquota.group  bin   dev  home        initrd.img.old  lib64       media  opt   root  sbin  srv  tmp  var      vmlinuz.old
aquota.user   boot  etc  initrd.img  lib             lost+found  mnt    proc  run   snap  sys  usr  vmlinuz

اگر گزینه های u یا g را در دستور quotacheck وارد نکرده باشید، فایل مربوطه از بین خواهد رفت.

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

sudo modprobe quota_v1 -S 5.4.0-99-generic
sudo modprobe quota_v2 -S 5.4.0-99-generic

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

sudo quotaon -v /

 

quotaon Output

/dev/vda1 [/]: group quotas turned on
/dev/vda1 [/]: user quotas turned on

سرور شما اکنون در حال نظارت و اجرای سهمیه ها است، اما ما هنوز هیچ کدام را تنظیم نکرده ایم! در مرحله بعد یک سهمیه دیسک برای یک کاربر تعیین می کنید.

مرحله 5 – پیکربندی سهمیه ها برای یک کاربر

چند راه برای تعیین سهمیه برای کاربران یا گروه ها وجود دارد. در اینجا، نحوه تنظیم سهمیه ها با هر دو دستور edquota و setquota را بررسی خواهید کرد.

استفاده از edquota برای تعیین سهمیه کاربر

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

sudo edquota -u sammy

گزینه -u مشخص می کند که این سهمیه کاربری است که شما در حال ویرایش آن هستید. اگر می خواهید سهمیه یک گروه را به جای آن ویرایش کنید، از گزینه -g در جای خود استفاده کنید.

با این کار، فایلی در ویرایشگر متن پیش‌فرض شما باز می‌شود، مشابه اینکه crontab -e یک فایل موقت را برای ویرایش شما باز می‌کند. فایل شبیه به این خواهد بود:

Disk quotas for user sammy (uid 1000):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/vda1                        40          0          0         13        0        0

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

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

بیایید کاربر سامی شما را به‌روزرسانی کنیم تا سهمیه بلوکی با محدودیت نرم افزاری 100 مگابایتی و محدودیت سخت 110 مگابایتی داشته باشد:

Disk quotas for user sammy (uid 1000):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/vda1                        40       100M       110M         13        0        0

ذخیره کنید و فایل را ببندید. برای بررسی سهمیه جدید می توانید از دستور quota استفاده کنید:

sudo quota -vs sammy

 

Output

Disk quotas for user sammy (uid 1000):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/vda1     40K    100M    110M              13       0       0

این فرمان وضعیت سهمیه فعلی شما را خروجی می دهد و نشان می دهد که سهمیه شما 100M است در حالی که حد شما 110M است. این به ترتیب با محدودیت های نرم و سخت مطابقت دارد.

استفاده از setquota برای تعیین سهمیه کاربر

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

sudo setquota -u sammy 200M 220M 0 0 /

دستور بالا محدودیت های سهمیه مبتنی بر بلوک سامی را به 200 مگابایت و 220 مگابایت دوبرابر می کند. 0 0 برای محدودیت های نرم و سخت مبتنی بر inode نشان می دهد که آنها تنظیم نشده باقی می مانند. این مورد نیاز است حتی اگر هیچ سهمیه مبتنی بر inode تنظیم نکنید.

یک بار دیگر از دستور quota برای بررسی کار خود استفاده کنید:

sudo quota -vs sammy

 

Output

Disk quotas for user sammy (uid 1000):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/vda1     40K    200M    220M              13       0       0

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

مرحله 6 – ایجاد گزارش های سهمیه

برای ایجاد گزارشی در مورد استفاده از سهمیه فعلی برای همه کاربران در یک فایل سیستم خاص، از دستور repquota استفاده کنید:

sudo repquota -s /

 

Output

*** Report for user quotas on device /dev/vda1
Block grace time: 7days; Inode grace time: 7days
                        Space limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --   1696M      0K      0K          75018     0     0
daemon    --     64K      0K      0K              4     0     0
man       --   1048K      0K      0K             81     0     0
nobody    --   7664K      0K      0K              3     0     0
syslog    --   2376K      0K      0K             12     0     0
sammy     --     40K    200M    220M             13     0     0

در این مثال شما در حال تولید یک گزارش برای فایل سیستم / root هستید. دستور -s به repquota می گوید که در صورت امکان از اعداد قابل خواندن توسط انسان استفاده کند. تعداد کمی از کاربران سیستم لیست شده اند که احتمالاً هیچ سهمیه ای به طور پیش فرض ندارند. سامی کاربر شما با مقادیر استفاده شده و محدودیت های نرم و سخت در پایین لیست شده است.

همچنین به Block grace time: 7days callout و ستون grace توجه کنید. اگر کاربر شما بیش از حد نرمال بود، ستون grace نشان می دهد که چقدر زمان برای بازگشت به زیر محدودیت باقی مانده است.

مرحله 7 – پیکربندی یک دوره مهلت برای بیش از حد

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

sudo setquota -t 864000 864000 /

دستور بالا هر دو زمان grace block و inode را روی 864000 ثانیه یا 10 روز تنظیم می کند. این تنظیم برای همه کاربران اعمال می‌شود و هر دو مقدار باید ارائه شوند حتی اگر از هر دو نوع سهمیه استفاده نمی‌کنید (block در مقابل inode).

توجه داشته باشید که مقادیر باید در ثانیه مشخص شوند.

دوباره repquota را اجرا کنید تا بررسی کنید که آیا تغییرات اعمال شده اند:

sudo repquota -s /

 

Output

Block grace time: 10days; Inode grace time: 10days
. . .

تغییرات باید بلافاصله در خروجی repquota منعکس شود.

نتیجه

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

پیوست: پیام های خطای رایج مربوط به سهمیه

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

 

quotaon Output

quotaon: cannot find //aquota.group on /dev/vda1 [/]
quotaon: cannot find //aquota.user on /dev/vda1 [/]

این خطایی است که ممکن است در صورت تلاش برای روشن کردن سهمیه ها (با استفاده از quotaon) قبل از اجرای فرمان quotacheck اولیه، مشاهده کنید. دستور quotacheck فایل های سهمیه یا سهمیه مورد نیاز برای روشن کردن سیستم سهمیه را ایجاد می کند. برای اطلاعات بیشتر به مرحله 4 مراجعه کنید.

 

quotaon Output

quotaon: using //aquota.group on /dev/vda1 [/]: No such process
quotaon: Quota format not supported in kernel.
quotaon: using //aquota.user on /dev/vda1 [/]: No such process
quotaon: Quota format not supported in kernel.

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

اگر اینطور است، با نصب بسته لینوکس-تصویر-اکسترا-مجازی با apt قابل رفع است. برای جزئیات بیشتر به مرحله 2 مراجعه کنید.

اگر این خطا پس از نصب ادامه داشت، مرحله 4 را مرور کنید. مطمئن شوید که یا به درستی از دستورات modprobe استفاده کرده اید، یا اگر این گزینه برای شما مناسب است، سرور خود را راه اندازی مجدد کرده اید.

 

quota Output

quota: Cannot open quotafile //aquota.user: Permission denied
quota: Cannot open quotafile //aquota.user: Permission denied
quota: Cannot open quotafile //quota.user: No such file or directory

اگر quota را اجرا کنید و کاربر فعلی شما مجوز خواندن فایل های سهمیه سیستم فایل شما را نداشته باشد، این خطایی است که مشاهده خواهید کرد. شما (یا مدیر سیستم شما) باید مجوزهای فایل را به درستی تنظیم کنید یا هنگام اجرای دستوراتی که نیاز به دسترسی به فایل سهمیه دارند از sudo استفاده کنید.

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:اتصال به سرور مجازیخرید سرور مجازیخرید سرور مجازی فرانسهخرید سرور مجازی قویدستور edquotaسرور اوبونتو 20.04سرور مجازیلینوکسماژول Quota Kernelنصب Quota Tools

 

  • behnam gol mohamadi
  • ۰
  • ۰

 نحوه استفاده از توابع در PHP

ورود به سایت

معرفی

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

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

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

توابع تعریف شده توسط کاربر

نوشتن کد یکسان در چندین مکان، خواندن و درک یک پروژه را دشوار می کند. یکی از “اصول اصلی” یا اصول اساسی برنامه نویسی “خودت را تکرار نکن” است که اغلب به آن برنامه نویسی DRY می گویند. متغیرها ما را از نوشتن مکرر داده های مشابه باز می دارند. توابع ما را از نوشتن مکرر یک عمل باز می دارند.

ایجاد و فراخوانی توابع

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

hello.php

<?php
function hello() {
    echo "Hello World!";
}

این تابع که hello نام دارد، غیر فعال می ماند، یعنی هیچ کاری انجام نمی دهد و تا زمانی که تابع فراخوانی نشود، فایل خروجی نخواهد داشت. برای فراخوانی یک تابع، از نام و به دنبال آن پرانتز استفاده می شود:

hello.php

<?php
function hello() {
    echo "Hello World!";
}
hello();

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

 

Output

Hello World!

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

hello.php

<?php
$hello = "Hello World!";
echo $hello;

این دو خط نتیجه مشابه تابع و فراخوانی را ارائه می دهند:

 

Output

Hello World!

اجازه دهید تابع مثال را برای پذیرش ورودی گسترش دهیم.

آرگومان ها و پارامترها

برای ایجاد یک تابع hello که رابطه ای بین ورودی و خروجی ایجاد می کند، تابع باید مقداری ورودی را بپذیرد. این ورودی به عنوان یک متغیر بین پرانتزهای تعریف تابع پذیرفته می شود. سپس این متغیر را می توان در بدنه تابع استفاده کرد:

hello.php

<?php
function hello($name) {
    echo "Hello ".$name;
}
hello();

تابع hello اکنون یک پارامتر ذخیره شده در متغیر $name را می پذیرد. سپس این متغیر در بدنه تابع با الحاق رشته “Hello” به متغیر $name با استفاده از . عملگر الحاق رشته ها اکنون تابع نیاز دارد که هنگام فراخوانی تابع، یک ورودی ارسال شود، اما ورودی ارائه نشده است، و باعث می شود PHP با خطا پاسخ دهد:

 

Output

Warning:  Uncaught ArgumentCountError: Too few arguments to function hello(), 0 passed in php shell code on line 1 and exactly 1 expected

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

hello.php

<?php
function hello($name) {
    echo "Hello ".$name;
}
hello("Sammy");

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

 

Output

Hello Sammy

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

مقادیر پیش فرض اختیاری

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

hello.php

<?php
function hello($name, $greeting = "Hello") {
    echo $greeting." ".$name;
}
hello("Sammy", "Bonjour");

اکنون یک پارامتر دوم به نام $greeting وجود دارد. سپس این متغیر در بدنه تابع برای تغییر مقدار بخش تبریک خروجی استفاده می شود:

 

Output

Bonjour Sammy

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

hello.php

<?php
function hello($name, $greeting = "Hello") {
    echo $greeting." ".$name;
}
hello("Sammy");

هنگامی که تنها یک آرگومان ارسال می شود، مقدار متغیر $greeting روی مقدار پیش فرض “Hello” تنظیم می شود:

 

Output

Hello Sammy

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

مقدار تهی اختیاری

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

hello.php

<?php
function hello($name, $greeting = "Hello", $punctuation = null) {
    echo $greeting." ".$name.$punctuation;
}
hello("Sammy");

متغیر is “اعلام شده” است، بنابراین هنگام تلاش بدنه تابع برای دسترسی به متغیر، خطایی وجود نخواهد داشت، و با این حال، متغیر “تنظیم نشده” در نظر گرفته می شود، بنابراین خروجی اضافی اضافه نخواهد شد:

 

Output

Hello Sammy

ارزش های بازگشتی

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

hello.php

<?php
function hello($name, $greeting = "Hello", $punctuation = null) {
    return $greeting." ".$name.$punctuation;
}
hello("Sammy");
echo hello("Sammy");

در اولین فراخوانی تابع hello، هیچ کاری با مقدار برگشتی انجام نمی شود، و به نظر می رسد که هیچ اتفاقی نیفتاده است، حتی اگر کد موجود در تابع اجرا شده باشد. در فراخوانی دوم تابع hello، کلمه کلیدی echo قبل از فراخوانی تابع استفاده می‌شود و به PHP می‌گوید نتایج خروجی برگشتی را چاپ کند:

 

Output

Hello Sammy

ما همیشه مجبور نیستیم نتیجه را چاپ کنیم. این نتایج همچنین می توانند در یک متغیر ذخیره شوند یا به عنوان ورودی برای تابع دیگری استفاده شوند.

فراخوانی توابع در یک تابع

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

hello.php

<?php
function hello($name, $greeting = "Hello", $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY");

خط اول در تابع hello اکنون مقداری قالب بندی برای مقدار $name اعمال می کند. ابتدا رشته را به حروف کوچک تبدیل می کند. تابع strtolower مقداری را برمی گرداند که بلافاصله در تابع دوم، ucwords استفاده می شود. این حرف اول هر کلمه را به حروف بزرگ تبدیل می کند. تابع hello اکنون بدون در نظر گرفتن ورودی دریافتی، یک خروجی با فرمت ثابت ارائه می دهد:

 

Output

Hello Sammy

اعلانات نوع

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

hello.php

<?php
function hello($name, $greeting = "Hello", $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello(123);

PHP هیچ گونه مشکلی در شعبده بازی ندارد، که عدد صحیح 123 را به رشته “123” تبدیل می کند، سپس تابع را مانند قبل ادامه می دهد:

 

Output

Hello 123

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

hello.php

<?php
function hello($name, $greeting = "Hello", $punctuation = null) {
    // $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello(["Sammy", "World"]);

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

 

Output

Notice: Array to string conversion in php shell code on line 2
Hello Array

توسعه دهندگان زمان بسیار بیشتری را صرف خواندن و اشکال زدایی می کنند تا اینکه واقعاً کد بنویسند، بنابراین هر کدی را که می نویسیم تا حد امکان برای خواندن و اشکال زدایی آسان تر کنیم، در دراز مدت در زمان صرفه جویی می شود. با شروع در PHP 5 و با پشتیبانی قوی تر در PHP 7، اکنون می توانیم انواع مقادیر قابل قبول ورودی و خروجی یک تابع را اعلام یا مشخص کنیم.

اعلان نوع پارامتر

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

hello.php

<?php
function hello(string $name, $greeting = "Hello", $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello(["Sammy", "World"]);

این بار فراخوانی تابع باعث ایجاد یک استثنا می شود که اجرای کد را متوقف می کند، بنابراین خروجی معتبری به نظر نمی رسد. پیام همچنین واضح تر است که خطا در واقع وجود دارد:

 

Output

Warning: Uncaught TypeError: Argument 1 passed to hello() must be of the type string, array given

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

hello.php

<?php
function hello(string $name, $greeting = "Hello", $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello(123);

به جای ارسال خطا، یک بار دیگر عدد صحیح بدون مشکل به رشته تبدیل می شود و تابع اجرا می شود:

 

Output

Hello 123

این مربوط به این است که PHP یک زبان تایپ آزاد است. PHP هنوز هم برای تبدیل آن به یک رشته، شعبده برداری از نوع را روی عدد صحیح انجام می دهد، سپس اجرا را ادامه می دهد.

انواع سختگیرانه

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

hello.php

<?php
declare(strict_types=1);
function hello(string $name, $greeting = "Hello", $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello(123);

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

 

Output

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to hello() must be of the type string, int given.

انواع Nullable

می‌توانیم پارامتر دوم تابع hello را نیز به عنوان یک رشته اعلام کنیم. چون مقدار پیش‌فرض دارد، نیازی به آرگومان نیست، اما اگر آرگومان ارسال شود، باید از نوع رشته باشد. پارامتر سوم نیز رشته ای با مقدار پیش فرض است. یک مقدار null نیز در این تابع کار می کند:

hello.php

<?php
declare(strict_types=1);
function hello(string $name, string $greeting = "Hello", string $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY", "Hola", null);

از آنجایی که مقدار پیش‌فرض پارامتر سوم روی null تنظیم شده است، آرگومان null و همچنین یک رشته مجاز است:

 

Output

Hola Sammy

با این حال، هنگامی که مقدار پیش فرض یک پارامتر به عنوان یک رشته اعلام می شود، دیگر مقدار تهی را نمی پذیرد:

hello.php

<?php
declare(strict_types=1);
function hello(string $name, string $greeting = "Hello", string $punctuation = "!") {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY", "Hola", null);

در عوض TypeError داده می شود:

 

Output

Warning: Uncaught TypeError: hello(): Argument #3 ($punctuation) must be of type string, null given

وقتی مقدار پیش‌فرض یک پارامتر چیزی غیر از null باشد، اما null نیز یک ورودی معتبر باشد، PHP دستور اضافی را برای تعریف آن رابطه با اضافه کردن یک علامت سوال قبل از اعلان نوع ارائه می‌کند:

hello.php

<?php
declare(strict_types=1);
function hello(string $name, string $greeting = "Hello", ?string $punctuation = null) {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY", "Hola", null);

حالا تابع آرگومان سوم null را می پذیرد و همانطور که قبلا پردازش شده است ادامه می دهد:

 

Output

Hola Sammy!

پیشوند علامت سوال با تمام اعلان‌های نوع کار می‌کند، نه فقط رشته‌ها، و نیازی به مقدار پیش‌فرض (مانند ?int $age) ندارد.

اعلامیه های نوع بازگشت

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

hello.php

<?php
declare(strict_types=1);
function hello(string $name, string $greeting = "Hello", ?string $punctuation = "!"): ?int {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY");

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

 

Output

Warning: Uncaught TypeError: hello(): Return value must be of type ?int, string returned

بیایید نوع بازگشتی را به روز کنیم تا با نوع رشته برگشتی مطابقت داشته باشد:

hello.php

<?php
declare(strict_types=1);
function hello(string $name, string $greeting = "Hello", ?string $punctuation = "!"): string {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY");

این خروجی را به ما می دهد که قبلاً دیده بودیم:

 

Output

Hello Sammy!

بدون ارزش برگشتی

گاهی اوقات یک تابع عملی را انجام می دهد که به مقدار برگشتی منجر نمی شود. تابع var_dump یک مثال است. اگر به اولین نسخه تابع hello برگردیم، می‌توانیم یک نوع بازگشتی void اضافه کنیم:

hello.php

<?php
function hello(): void {
    echo "Hello World!";
}
$greeting = hello();
var_dump($greeting);

این نشان می دهد که تابع مقداری را بر نمی گرداند. هنگامی که تابع فراخوانی می شود و روی یک متغیر اعمال می شود، خروجی نمایش داده می شود زیرا کلمه کلیدی echo در خود تابع استفاده می شود. با استفاده از var_dump در متغیر $greeting، می‌بینیم که هیچ مقداری برگردانده نشده است و متغیر $greeting روی یک مقدار null تنظیم می‌شود:

 

Output

Hello World!
NULL

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

محدوده

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

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

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

از آنجایی که PHP این دو حوزه را به‌عنوان موجودیت‌های مجزا در نظر می‌گیرد، زمانی که یک متغیر به یک تابع ارسال می‌شود، «مقدار» متغیر ارسال می‌شود و نه خود متغیر. بیایید یک متغیر سراسری تنظیم کنیم تا ببینیم این به چه معناست برای کد:

hello.php

<?php
declare(strict_types=1);
$name = "SAMMY";
function hello(string $name, string $greeting = "Hello", ?string $punctuation = "!"): string {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello($name);
echo $name;

به جای ارسال مستقیم یک رشته، اکنون یک متغیر رشته را ارسال می کنیم. این متغیر به همان شیوه ای عمل می کند که یک رشته را به طور مستقیم ارسال می کند زیرا فقط از مقدار متغیر استفاده می شود. هنگامی که مقدار متغیر $name در تابع تغییر می کند، فقط متغیر $name در تابع تحت تأثیر قرار می گیرد. متغیر $name در دامنه جهانی یک متغیر جداگانه است:

 

Output

Hello Sammy!
SAMMY

خروجی echo hello($name) “Hello Sammy” است، زیرا این مقداری است که توسط تابعی که با آرگومان $name ارائه شده است، برگردانده می شود. حتی پس از فراخوانی تابع، مقدار متغیر $name در محدوده جهانی تغییر نمی کند، بنابراین خروجی echo $name; “SAMMY” است، زیرا متغیر جهانی روی “SAMMY” تنظیم می شود.

دسترسی به گستره جهانی

یک تفاوت بزرگ بین دامنه جهانی و دامنه تابع این است که شما می توانید به یک تابع اجازه دهید تا برای بازیابی داده ها به دامنه جهانی برسد، اما نمی توانید داده ها را مستقیماً از یک تابع در دامنه جهانی بازیابی کنید. کلمه کلیدی جهانی به دامنه جهانی می رسد:

hello.php

<?php
declare(strict_types=1);
$name = "SAMMY";
function hello(string $greeting = "Hello", ?string $punctuation = "!"): string {
    global $name;
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello();
echo $name;

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

 

Output

Hello Sammy!
Sammy

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

گذراندن استدلال ها با مرجع

پی اچ پی آرگومان ها را به عنوان مقادیر می خواند. فرقی نمی‌کند که متغیری حاوی رشته «SAMMY» یا خود رشته را پاس کنیم. فقط از مقدار استفاده می شود. عبور از مقدار از همپوشانی دامنه جهانی و دامنه عملکرد جلوگیری می کند. از آنجا که یک تابع ممکن است مقداری را برگرداند، می‌توانیم از آن مقدار برای تنظیم هر متغیری در یک محدوده جداگانه استفاده کنیم، حتی یکی از آن‌ها به عنوان آرگومان استفاده می‌شود. با نوشتن کد به این روش، مدیریت یک متغیر به وضوح در محدوده اصلی نگهداری می شود. مثال‌های قبلی مقدار متغیر $name را با نادیده گرفتن مقدار متغیر برای مطابقت با مقدار بازگشتی برخی از توابع داخلی تغییر داده‌اند. بیایید نگاهی دقیق‌تر به قالب‌بندی ucwords و strtolower بیندازیم:

$name = "SAMMY";
$name = ucwords(strtolower($name));
echo $name;

این مقدار جدید $name اکنون قالب بندی جدیدی دارد:

 

Output

Sammy

در حالی که یک تابع فقط می تواند یک مقدار را برگرداند، یک تابع ممکن است بیش از یک متغیر را تحت تأثیر قرار دهد. در مثال‌هایی که نوشتیم، تابع hello از چندین متغیر استفاده می‌کند اما مقدار آن متغیرها را در محدوده جهانی تغییر نمی‌دهد. PHP راهی را برای تعامل مستقیم با یک متغیر از محدوده دیگر، با ارسال یک مرجع به خود متغیر، نه فقط مقدار آن، فراهم می کند. آرگومان ها با ارجاع با افزودن علامت (&) به هر پارامتری منتقل می شوند:

hello.php

<?php
declare(strict_types=1);
$name = "SAMMY";
function hello(string &$name, string $greeting = "Hello", ?string $punctuation = "!"): void {
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello($name);
echo $name;

هنگامی که متغیر $name توسط مرجع ارسال می شود، مقدار آن متغیر را در محدوده جهانی تغییر می دهد. پس از فراخوانی تابع، $name قالب بندی را حفظ می کند:

 

Output

Hello Sammy!
Sammy

هنگام عبور از مرجع، آرگومان باید یک متغیر باشد. یک مقدار دیگر پذیرفته نمی شود:

hello.php

<?php
declare(strict_types=1);
function hello(string &$name, string $greeting = "Hello", ?string $punctuation = "!"): string {
    global $name;
    $name = ucwords(strtolower($name));
    return $greeting." ".$name.$punctuation;
}
echo hello("SAMMY");

از آنجایی که هیچ متغیری برای مرجع وجود ندارد، یک خطا داده می شود:

 

Output

Warning: Uncaught Error: hello(): Argument #1 ($name) cannot be passed by reference

توابع داخلی

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

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

توابع مدیریت متغیر

توابع مدیریت متغیر جزئیاتی را در مورد یک متغیر مانند نوع یا مقدار آن ارائه می دهند. یکی از رایج ترین توابع مدیریت متغیر var_dump است:

hello.php

<?php
var_dump("Hello World!");

این تابع جزئیات مقادیر داده شده را شامل نوع و اندازه آنها می دهد. رشته “سلام دنیا!” شامل 12 کاراکتر:

 

Output

string(12) "Hello World!"

PHP همچنین توابع اضافی را برای تعامل با مقدار متغیرهای نوع خاص فراهم می کند.

نتیجه

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

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

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:serverآرگومان ها و پارامترهااستفاده از توابع در PHPانواع Nullableپی اچ پیتوابع داخلی در phpخرید سرور مجازیخرید سرور مجازی آمریکاسرور مجازیمدیریت توابع متغیر در php

 

  • behnam gol mohamadi
  • ۰
  • ۰

 چگونه سرورهای اوبونتو 20.04 را به روز نگه داریم

ورود به سایت

معرفی

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

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

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

پیش نیازها

یک سرور اوبونتو 20.04 و یک کاربر غیر ریشه با امتیازات sudo.

مرحله 1 – پیروی از بهترین روش ها برای مدیریت برنامه

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

در صورت امکان، برنامه های موجود در پشته شما باید توسط سیستم init سرور شما مدیریت شود، که در اکثر توزیع های لینوکس مدرن از جمله اوبونتو سیستمی است. Systemd دستور systemctl را برای تعامل با سرویس های در حال اجرا و راه اندازی مجدد خودکار آنها در صورت نیاز ارائه می دهد. تقریباً تمام نرم افزارهایی که از طریق مدیریت بسته شما نصب می شوند و برای اجرا در پس زمینه طراحی می شوند، باید به طور خودکار یک سرویس systemd و یک فایل واحد پیکربندی را به عنوان بهترین روش ارائه دهند.

هنگام اجرای نرم افزار خود، یا نرم افزار مستقر شده از مخازن Git، ایده بدی نیست که فایل های واحد خود را برای ادغام با systemd بنویسید. به عنوان یک جایگزین سبک، ممکن است ترجیح دهید از ابزاری مانند سرپرست استفاده کنید. همچنین می‌توانید از زمان‌بندی cron سیستم خود با دستور reboot@ استفاده کنید.

پس از اینکه پیکربندی در جای خود قرار گرفت، مطمئن شوید که آن را از طریق راه اندازی مجدد تست کنید. می‌توانید با اجرای sudo shutdown now -r راه‌اندازی مجدد کنید، که فرآیندهای در حال اجرا شما را کاملاً متوقف می‌کند و بلافاصله راه‌اندازی مجدد می‌شود. همچنین می‌توانید به‌جای زمان کنونی، زمان را به hh:mm یا چند دقیقه از هم‌اکنون تعیین کنید تا در آینده راه‌اندازی مجدد را برنامه‌ریزی کنید. استقرار تولید معمولاً پس از قطعی های برنامه ریزی نشده نیازی به توجه شما ندارد و همه سرویس ها و نقاط پایانی لازم باید به طور خودکار بازیابی شوند.

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

مرحله 2 – پیکربندی ارتقاءهای بدون نظارت

مدیر بسته اوبونتو، apt، دارای یک گردش کار کاملاً ثابت برای انجام یک ارتقاء کامل سیستم است. ابتدا، آپدیت apt را اجرا می‌کنید تا لیست بسته‌های خود را به‌روزرسانی کنید، و سپس، apt upgrade را بدون مشخص کردن بسته‌ای اجرا می‌کنید تا هر بسته در سیستم را ارتقا دهید. اگر با بسته‌های شخص ثالث تداخل نسخه داشته باشید یا اگر عمداً برخی از بسته‌ها را ارتقا نداده‌اید، این گردش کار ممکن است کمی متفاوت باشد، اما دستورات اصلی یکسان هستند.

اوبونتو یک ابزار منحصر به فرد به نام ارتقاهای بدون نظارت را به منظور بازیابی و نصب خودکار وصله های امنیتی و سایر ارتقاءهای ضروری برای سرور شما فراهم می کند. اکثر سرورهای اوبونتو با این ابزار به صورت خودکار نصب و پیکربندی می شوند، اما می توانید آن را با دستورات apt زیر نصب کنید:

sudo apt update
sudo apt install unattended-upgrades

پس از نصب، می توانید بررسی کنید که آیا سرویس ارتقاء بدون نظارت با استفاده از systemctl اجرا می شود:

sudo systemctl status unattended-upgrades.service

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

پیکربندی آن در /etc/apt/apt.conf.d/50unattended-upgrades ذخیره می شود. این فایل را با استفاده از nano یا ویرایشگر متن مورد علاقه خود باز کنید:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

فایل به خوبی حاشیه نویسی شده است، و می توانید خطوط بسیاری از نظرات کد (با //) را ببینید که عملکرد آن را توضیح می دهند. اولین بلوک پیکربندی، بسته‌هایی را که به‌طور خودکار به‌روزرسانی می‌شوند، بررسی می‌کند و با الگوی نام‌های مخزن بسته اوبونتو مطابقت دارد. فایل‌های موجود در مخزن هسته و مخزن -security به طور پیش‌فرض به‌روزرسانی می‌شوند، اما خطوط حاوی مخازن -updates، -proposed و -backports به‌طور پیش‌فرض نظر داده می‌شوند.

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

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

پس از اتمام ویرایش فایل را ذخیره کرده و ببندید. اگر از nano استفاده می کنید، Ctrl+X را فشار دهید، سپس وقتی از شما خواسته شد، Y و سپس Enter را فشار دهید.

اگر تغییراتی در پیکربندی ایجاد کردید، سرویس ارتقاهای بدون نظارت را مجدداً بارگیری کنید تا اعمال شود:

sudo systemctl reload unattended-upgrades.service

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

مرحله 3 – به روز رسانی و LivePatching هسته

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

هیچ روش جهانی برای زمان بندی خودکار به روز رسانی هسته لینوکس وجود ندارد. این به این دلیل است که به‌روزرسانی‌های هسته از گذشته نیازمند راه‌اندازی مجدد کامل سیستم بوده‌اند و زمان‌بندی راه‌اندازی مجدد بدون ایجاد فرضیاتی در مورد محیط شما غیرممکن است. انتظار می‌رود که بسیاری از سرورها تا حد امکان در دسترس بودن 24 ساعته و 7 روز هفته را ارائه دهند و راه‌اندازی مجدد می‌تواند مدت زمان نامعلومی طول بکشد یا نیاز به مداخله دستی داشته باشد.

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

فعال کردن Livepatch برای اطمینان از Uptime سرور در طول به روز رسانی هسته

برای جلوگیری از خرابی در هنگام ارتقای هسته، می توانید از ویژگی هسته لینوکس به نام وصله زنده استفاده کنید. این ویژگی امکان پیاده سازی به روز رسانی هسته را بدون راه اندازی مجدد می دهد. دو نگهدارنده اصلی برای وصله‌های زنده هسته وجود دارد: Canonical، که سرویس Livepatch خود را برای اوبونتو ارائه می‌کند، و KernelCare که اوبونتو را علاوه بر سایر توزیع‌های اصلی لینوکس پشتیبانی می‌کند. هر دو برای استفاده نیاز به ثبت نام دارند و فقط سرویس Canonical برای استفاده فردی رایگان است.

می توانید برای یک کلید Livepatch در https://auth.livepatch.canonical.com/ ثبت نام کنید. پس از ثبت نام، می توانید بسته snap canonical-livepatch را نصب کنید. Snap یکی دیگر از مدیریت بسته های اوبونتو است که در کنار apt اجرا می شود.

sudo snap install canonical-livepatch

می‌توانید با استفاده از کلید وب‌سایت آن‌ها، با فرمان یک خطی، canonical-livepatch را فعال کنید:

sudo canonical-livepatch enable your-key

خروجی باید حاوی پیام Successfully enabled device باشد. این سرویس باید از این پس بدون هیچ گونه مداخله دیگری در پس زمینه اجرا شود و می توانید وضعیت آن را با استفاده از وضعیت canonical-livepatch بررسی کنید:

sudo canonical-livepatch status

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

نتیجه

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

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:LivePatching هستهاتصال به سرور مجازیبه روز رسانی سرورخرید سرور مجازیراه اندازی سرورسرور مجازیسرورهای اوبونتو 20.04فعال کردن Livepatch

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از MongoDB در یک برنامه Flask

ورود به سایت

معرفی

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

Flask یک چارچوب وب سبک وزن پایتون است که ابزارها و ویژگی های مفیدی را برای ایجاد برنامه های کاربردی وب در زبان پایتون ارائه می دهد. MongoDB یک برنامه پایگاه داده NoSQL برای همه منظوره، سند محور است که از اسناد JSON مانند برای ذخیره داده ها استفاده می کند. برخلاف روابط جدولی که در پایگاه‌های اطلاعاتی رابطه‌ای استفاده می‌شود، اسناد JSON مانند امکان ایجاد طرح‌واره‌های انعطاف‌پذیر و پویا را در عین سادگی حفظ می‌کنند. به طور کلی، پایگاه های داده NoSQL توانایی مقیاس افقی را دارند که آنها را برای داده های بزرگ و برنامه های بلادرنگ مناسب می کند.

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

پیش نیازها

  • یک محیط برنامه نویسی محلی Python 3، آموزش توزیع خود را در نحوه نصب و راه اندازی یک محیط برنامه نویسی محلی برای سری Python 3 دنبال کنید. در این آموزش ما دایرکتوری پروژه خود را flask_app می نامیم.
  • MongoDB روی دستگاه محلی شما نصب شده است. راهنمای نحوه نصب MongoDB در اوبونتو 20.04 را برای تنظیم پایگاه داده MongoDB خود دنبال کنید.
  • درک مفاهیم پایه فلاسک، مانند مسیرها، توابع مشاهده، و الگوها. اگر با Flask آشنایی ندارید، نحوه ایجاد اولین برنامه وب خود با استفاده از Flask و Python و نحوه استفاده از الگوها در یک برنامه Flask را بررسی کنید.
  • درک مفاهیم اولیه HTML برای آگاهی از پیشینه، می‌توانید مجموعه آموزش نحوه ساخت یک وب‌سایت با HTML را مرور کنید.

مرحله 1 – راه اندازی PyMongo و Flask

در این مرحله Flask و کتابخانه PyMongo را نصب خواهید کرد.

با فعال شدن محیط مجازی، از pip برای نصب Flask و PyMongo استفاده کنید:

pip install Flask pymongo

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

 

Output

Successfully installed Flask-2.0.2 Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 itsdangerous-2.0.1 pymongo-4.0.1

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

مرحله 2 – اتصال به سرور MongoDB و ایجاد یک مجموعه

در این مرحله، از کتابخانه PyMongo برای ایجاد یک کلاینت استفاده می‌کنید که از آن برای تعامل با سرور MongoDB، ایجاد یک پایگاه داده، و سپس ایجاد مجموعه‌ای برای ذخیره کارهای خود استفاده می‌کنید.

با فعال بودن محیط برنامه نویسی خود، فایلی به نام app.py را برای ویرایش در پوشه flask_app خود باز کنید:

nano app.py

این فایل کلاس و راهنماهای لازم را از Flask و کتابخانه PyMongo وارد می کند. شما با سرور MongoDB خود برای ایجاد یک پایگاه داده و ایجاد مجموعه ای برای کارها تعامل خواهید داشت. کد زیر را به app.py اضافه کنید:

flask_app/app.py

from flask import Flask
from pymongo import MongoClient

app = Flask(__name__)

client = MongoClient('localhost', 27017)

db = client.flask_db
todos = db.todos

ذخیره کنید و فایل را ببندید.

در اینجا شما کلاس Flask را وارد می کنید، که از آن برای ایجاد یک نمونه برنامه کاربردی Flask به نام app استفاده می کنید.

شما MongoClient را وارد می کنید که از آن برای ایجاد یک شی کلاینت برای نمونه MongoDB به نام کلاینت استفاده می کنید، که به شما امکان می دهد با سرور MongoDB خود ارتباط برقرار کنید و با آن تعامل داشته باشید. وقتی MongoClient را نمونه‌سازی می‌کنید، آن را به میزبان سرور MongoDB خود، که در مورد ما localhost است، و پورت را که در اینجا 27017 است، منتقل می‌کنید.

سپس از نمونه مشتری برای ایجاد یک پایگاه داده MongoDB به نام flask_db استفاده می کنید و یک مرجع به آن را در متغیری به نام db ذخیره می کنید.

سپس مجموعه ای به نام todos در پایگاه داده flask_db با استفاده از متغیر db ایجاد می کنید. مجموعه ها گروهی از اسناد را در MongoDB ذخیره می کنند، مانند جداول در پایگاه های داده رابطه ای.

در MongoDB، پایگاه داده ها و مجموعه ها با تنبلی ایجاد می شوند. این به این معنی است که حتی اگر فایل app.py را اجرا کنید، تا زمانی که اولین سند ایجاد نشود، هیچ یک از کدهای مربوط به پایگاه داده اجرا نخواهد شد. شما یک برنامه کوچک Flask با صفحه ای ایجاد خواهید کرد که به کاربران اجازه می دهد در مرحله بعد اسناد todo را در مجموعه کارهای شما وارد کنند. هنگامی که اولین سند todo اضافه شد، پایگاه داده flask_db و مجموعه todos در سرور MongoDB شما ایجاد می شود.

برای دریافت لیستی از پایگاه های داده فعلی خود، یک ترمینال جدید باز کنید و پوسته mongo را با استفاده از دستور زیر راه اندازی کنید:

mongo

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

show dbs

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

متوجه خواهید شد که flask_db هنوز وجود ندارد. پوسته مونگو را در پنجره ترمینال بگذارید و به مرحله بعد ادامه دهید.

مرحله 3 – ایجاد یک صفحه وب برای افزودن و نمایش کارها

در این مرحله، یک صفحه وب با یک فرم وب ایجاد می‌کنید که به کاربران اجازه می‌دهد تا کارها را اضافه کرده و در همان صفحه نمایش دهند.

با فعال بودن محیط برنامه نویسی، فایل app.py خود را برای ویرایش باز کنید:

nano app.py

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

flask_app/app.py

from flask import Flask, render_template, request, url_for, redirect
from pymongo import MongoClient

# ...

در اینجا، تابع render_template() کمکی را که برای رندر یک قالب HTML استفاده می کنید، شی درخواست برای دسترسی به داده هایی که کاربر ارسال می کند، تابع url_for() برای تولید URL و تابع redirect() برای تغییر مسیر کاربر وارد می کنید. پس از افزودن یک کار به صفحه فهرست بازگردید.

سپس مسیر زیر را در انتهای فایل اضافه کنید:

flask_app/app.py

# ...


@app.route('/', methods=('GET', 'POST'))
def index():
    return render_template('index.html')

ذخیره کنید و فایل را ببندید.

در این مسیر، تاپل (“GET”، “POST”) را به پارامتر متد ارسال می کنید تا درخواست های GET و POST را مجاز کنید. درخواست های GET برای بازیابی داده ها از سرور استفاده می شود. درخواست های POST برای ارسال داده ها به یک مسیر خاص استفاده می شود. به طور پیش فرض، فقط درخواست های GET مجاز هستند. هنگامی که کاربر برای اولین بار مسیر / را با استفاده از یک درخواست GET درخواست می کند، یک فایل الگو به نام index.html ارائه می شود. شما بعداً این مسیر را برای رسیدگی به درخواست‌های POST برای زمانی که کاربران فرم وب را برای ایجاد کارهای جدید پر کرده و ارسال می‌کنند، ویرایش خواهید کرد.

سپس یک پوشه templates در پوشه flask_app خود و الگوی index.html که در مسیر قبلی به آن اشاره کردید ایجاد کنید:

mkdir templates
nano templates/index.html

کد زیر را داخل فایل index.html اضافه کنید:

flask_app/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FlaskApp</title>
    <style>
        .todo {
            padding: 20px;
            margin: 10px;
            background-color: #eee;
        }
    </style>
</head>
<body>
    <h1>FlaskTODO</h1>
    <hr>
    <div class="content">
    <form method="post">
        <p>
            <b><label for="content">Todo content</label></b>
        </p>
        <p>
            <input type="text" name="content"
                placeholder="Todo Content"></input>
        </p>

        <p>
            <b><label for="degree">Degree</label></b>
        </p>
        <p>
            <input id="degree-0" name="degree" required type="radio" value="Important">
            <label for="degree-0">Important</label>
        </p>
        <p>
            <input id="degree-1" name="degree" required type="radio" value="Unimportant">
            <label for="degree-1">Unimportant</label>
        </p>
        <button type="submit">Submit</button>
    </form>
    </div>
</body>
</html>

ذخیره کنید و فایل را ببندید.

در اینجا شما یک صفحه اصلی HTML با عنوان، چند سبک، عنوان و یک فرم وب دارید. در فرم وب، ویژگی متد را برای ارسال نشان می دهید که فرم درخواست POST ارسال می کند. شما یک فیلد ورودی متنی برای محتوای todo با محتوای نام دارید که برای دسترسی به داده های عنوان در مسیر / از آن استفاده می کنید. شما همچنین دو دکمه رادیویی HTML با درجه نام دارید که به کاربر امکان می‌دهد درجه اهمیت هر مورد را مشخص کند: آنها می‌توانند گزینه مهم یا گزینه غیرممکن را هنگام ایجاد کار انتخاب کنند. در آخر، شما یک دکمه ارسال در انتهای فرم دارید.

در حالی که در دایرکتوری flask_app خود با محیط مجازی فعال هستید، با استفاده از متغیر محیطی FLASK_APP به Flask در مورد برنامه (در این مورد app.py) بگویید. سپس متغیر محیطی FLASK_ENV را روی توسعه تنظیم کنید تا برنامه در حالت توسعه اجرا شود و به دیباگر دسترسی پیدا کنید. برای اطلاعات بیشتر در مورد اشکال زدا Flask، به نحوه رسیدگی به خطاها در یک برنامه فلاسک مراجعه کنید. برای این کار از دستورات زیر استفاده کنید:

export FLASK_APP=app
export FLASK_ENV=development

بعد، برنامه را اجرا کنید:

flask run

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

http://127.0.0.1:5000/

صفحه فهرست را با یک فیلد ورودی برای محتوای todo، دو دکمه رادیویی برای درجه اهمیت و یک دکمه ارسال خواهید دید.

برای اطلاعات بیشتر در مورد فرم های وب، نحوه استفاده از فرم های وب در یک برنامه فلاسک را ببینید. برای یک روش پیشرفته تر و ایمن تر برای مدیریت فرم های وب، به نحوه استفاده و اعتبارسنجی فرم های وب با Flask-WTF مراجعه کنید.

اگر فرم را پر کنید و ارسال کنید، با ارسال یک درخواست POST به سرور، هیچ اتفاقی نمی افتد زیرا شما درخواست های POST را در مسیر / رسیدگی نکرده اید.

سرور را در حال اجرا بگذارید و یک پنجره ترمینال جدید باز کنید.

برای رسیدگی به درخواست POST که کاربر ارسال می کند، app.py را باز کنید، آنها را به مجموعه کارها اضافه کنید و در صفحه فهرست نمایش دهید:

nano app.py

مسیر / را به شکل زیر ویرایش کنید:

flask_app/app.py

@app.route('/', methods=('GET', 'POST'))
def index():
    if request.method=='POST':
        content = request.form['content']
        degree = request.form['degree']
        todos.insert_one({'content': content, 'degree': degree})
        return redirect(url_for('index'))

    all_todos = todos.find()
    return render_template('index.html', todos=all_todos)

ذخیره کنید و فایل را ببندید.

در این تغییرات، شما درخواست های POST را در داخل شرط if request.method == ‘POST’ مدیریت می کنید. شما محتوای todo و درجه اهمیتی که کاربر ارسال می کند را از شی request.form استخراج می کنید.

شما از متد insert_one() در مجموعه todos برای اضافه کردن یک سند todo به آن استفاده می کنید. شما داده‌های todo را در فرهنگ لغت پایتون ارائه می‌دهید، «محتوا» را روی مقداری که کاربر در قسمت متن برای محتوای todo ارسال کرده است، تنظیم می‌کنید و کلید «درجه» را روی مقدار دکمه رادیویی که کاربر انتخاب می‌کند، تنظیم می‌کنید. سپس به صفحه فهرست هدایت می‌شوید، که صفحه را تازه می‌کند و آیتم جدید اضافه شده را نمایش می‌دهد.

برای نمایش تمام کارهای ذخیره شده، از متد find() خارج از کدی که مسئول رسیدگی به درخواست‌های POST است استفاده می‌کنید، که تمام اسناد todo موجود در مجموعه todos را برمی‌گرداند. کارهایی را که از پایگاه داده دریافت می کنید در متغیری به نام all_todos ذخیره می کنید و سپس فراخوانی تابع render_template() را ویرایش می کنید تا لیست اسناد todo را به قالب index.html منتقل کنید، که در قالب در متغیری به نام موجود خواهد بود. کارها

اگر صفحه فهرست را بازخوانی کنید، ممکن است پیامی از مرورگر دریافت کنید که از شما می خواهد ارسال مجدد فرم را تأیید کنید. اگر بپذیرید، مورد todo که قبلاً قبل از رسیدگی به درخواست‌های POST ارسال کرده‌اید، سپس به پایگاه داده اضافه می‌شود، زیرا کد رسیدگی به فرم‌ها اکنون در مسیر وجود دارد.

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

use flask_db

سپس از تابع find() برای دریافت همه موارد todo در پایگاه داده استفاده کنید:

db.todos.find()

اگر داده‌ای دوباره ارسال شد، آن را اینجا در خروجی خود خواهید دید.

سپس، قالب index.html را باز کنید تا محتویات لیست کارهایی که به آن ارسال کرده اید نمایش داده شود:

nano templates/index.html

فایل را با اضافه کردن یک شکست <hr> و یک حلقه Jinja برای بعد از فرم ویرایش کنید، به طوری که فایل به شکل زیر باشد:

flask_app/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FlaskApp</title>
    <style>
        .todo {
            padding: 20px;
            margin: 10px;
            background-color: #eee;
        }
    </style>
</head>
<body>
    <h1>FlaskTODO</h1>
    <hr>
    <div class="content">
    <form method="post">
        <p>
            <b><label for="content">Todo content</label></b>
        </p>
        <p>
            <input type="text" name="content"
                placeholder="Todo Content"></input>
        </p>

        <p>
            <b><label for="degree">Degree</label></b>
        </p>
        <p>
            <input id="degree-0" name="degree" required type="radio" value="Important">
            <label for="degree-0">Important</label>
        </p>
        <p>
            <input id="degree-1" name="degree" required type="radio" value="Unimportant">
            <label for="degree-1">Unimportant</label>
        </p>
        <button type="submit">Submit</button>
    </form>
    <hr>
    {% for todo in todos %}
        <div class="todo">
            <p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
        </div>
    {% endfor %}

    </div>
</body>
</html>

ذخیره کنید و فایل را ببندید.

در این فایل، یک تگ <hr> اضافه می‌کنید تا فرم وب و لیست کارها را جدا کنید.

شما از یک حلقه for در خط {% for todo in todos %} برای عبور از هر مورد در لیست کارها استفاده می کنید. شما محتوای todo و درجه اهمیت را در یک تگ <p> نمایش می دهید.

اکنون صفحه فهرست خود را بازخوانی کنید، فرم وب را پر کنید و آن را ارسال کنید. کارهایی که اضافه کردید را در زیر فرم خواهید دید. در مرحله بعد، دکمه ای اضافه می کنید که به کاربران اجازه می دهد کارهای موجود را حذف کنند.

مرحله 4 – حذف Todos

در این مرحله، مسیری را اضافه می‌کنید که به کاربران اجازه می‌دهد تا با استفاده از یک دکمه، کارها را حذف کنند.

ابتدا، یک مسیر /id/delete جدید اضافه می‌کنید که درخواست‌های POST را می‌پذیرد. تابع view delete() جدید شما شناسه کاری را که باید از URL حذف شود دریافت می کند، سپس از آن شناسه برای حذف آن استفاده کنید.

برای حذف یک todo، شناسه آن را به عنوان یک رشته دریافت می‌کنید و باید قبل از ارسال آن به روش حذف مجموعه، آن را به ObjectId تبدیل کنید. بنابراین باید کلاس ObjectId() را از ماژول bson وارد کنید، که کدگذاری و رمزگشایی BSON (Binary JSON) را مدیریت می کند.

برای ویرایش app.py را باز کنید:

nano app.py

ابتدا وارد کردن زیر را در بالای فایل اضافه کنید:

flask_app/app.py

from bson.objectid import ObjectId

# ...

این کلاس ObjectId() است که از آن برای تبدیل شناسه رشته ها به اشیاء ObjectId استفاده می کنید.

سپس مسیر زیر را در پایان اضافه کنید:

flask_app/app.py

# ...


@app.post('/<id>/delete/')
def delete(id):
    todos.delete_one({"_id": ObjectId(id)})
    return redirect(url_for('index'))

ذخیره کنید و فایل را ببندید.

در اینجا، به جای استفاده از دکوراتور معمولی app.route، از دکوراتور app.post معرفی شده در Flask نسخه 2.0.0 استفاده می کنید که میانبرهایی را برای روش های رایج HTTP اضافه می کند. برای مثال، @app.post(“/login”) یک میانبر برای @app.route(“/login”، method=[“POST”]) است. این بدان معناست که این تابع view فقط درخواست‌های POST را می‌پذیرد، و پیمایش به مسیر /ID/delete در مرورگر شما، خطای 405 Method Not Allowed را برمی‌گرداند، زیرا مرورگرهای وب به‌طور پیش‌فرض درخواست‌های GET را دارند. برای حذف یک todo، کاربر روی دکمه ای کلیک می کند که درخواست POST را به این مسیر ارسال می کند.

تابع شناسه سند کاری را که باید حذف شود دریافت می کند. شما این شناسه را به متد ()delete_one در مجموعه todos ارسال می‌کنید و شناسه رشته‌ای را که دریافت می‌کنید با استفاده از کلاس ObjectId() که قبلاً وارد کرده‌اید به ObjectId تبدیل می‌کنید.

پس از حذف سند todo، کاربر را به صفحه فهرست هدایت می کنید.

سپس، قالب index.html را ویرایش کنید تا دکمه Delete Todo اضافه شود:

nano templates/index.html

حلقه for را با افزودن یک تگ <form> جدید ویرایش کنید:

flask_app/templates/index.html

    {% for todo in todos %}
        <div class="todo">
            <p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
            <form method="POST" action="{{ url_for('delete', id=todo['_id']) }}" >
                <input type="submit" value="Delete Todo"
                       onclick="return confirm('Are you sure you want to delete this entry?')">
            </form>
        </div>
    {% endfor %}

ذخیره کنید و فایل را ببندید.

در اینجا، یک فرم وب دارید که یک درخواست POST را به تابع view delete() ارسال می کند. شما به todo[‘_id’] منتقل می‌کنید تا کاری را که حذف می‌شود، مشخص کنید. شما از متد ()firm موجود در مرورگرهای وب برای نمایش پیام تایید قبل از ارسال درخواست استفاده می کنید.

اکنون صفحه فهرست خود را بازخوانی کنید و دکمه Delete Todo را در زیر هر مورد انجام دهید. روی آن کلیک کنید و حذف را تایید کنید. شما به صفحه فهرست هدایت می شوید و کار دیگر در آنجا وجود نخواهد داشت.

اکنون راهی برای حذف کارهای ناخواسته از پایگاه داده mongoDB خود در برنامه Flask خود دارید.

برای تایید حذف، پوسته مونگو خود را باز کنید و از تابع find() استفاده کنید:

db.todos.find()

باید ببینید که مواردی که حذف کرده اید دیگر در مجموعه کارهای شما نیستند.

نتیجه

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

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:اتصال به سرور MongoDBاتصال به سرور مجازیبرنامه Flaskبرنامه های کاربردی وبپایتونحذف Todosخرید سرور مجازیخرید سرور مجازی قویراه اندازی PyMongoسرور مجازینحوه استفاده از MongoDB

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از تاریخ و زمان در Go

ورود به سایت

معرفی

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

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

پیش نیازها

Go نسخه 1.16 یا بالاتر نصب شده است، که می توانید با دنبال کردن سری ما، نحوه نصب و راه اندازی یک محیط برنامه نویسی محلی برای Go، این کار را انجام دهید.

دریافت زمان فعلی

در این بخش، زمان فعلی را با استفاده از بسته زمانی Go دریافت خواهید کرد. بسته زمانی در کتابخانه استاندارد Go انواع توابع مربوط به تاریخ و زمان را ارائه می‌کند و می‌تواند برای نمایش یک نقطه خاص در زمان با استفاده از نوع time.Time استفاده شود. علاوه بر زمان و تاریخ، می‌تواند اطلاعاتی در مورد منطقه زمانی که تاریخ و زمان نمایش داده شده در آن قرار دارد نیز در خود جای دهد.

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

دایرکتوری پروژه ها را بسازید و به آن بروید:

mkdir projects

cd projects

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

nano main.go

در فایل main.go، یک تابع اصلی اضافه کنید که زمان جاری را دریافت کرده و آن را چاپ می کند:

projects/datetime/main.go

package main

import (
	"fmt"
	"time"
)

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
}

در این برنامه تابع time.Now از بسته زمان برای دریافت زمان محلی فعلی به عنوان مقدار time.Time استفاده می شود و سپس آن را در متغیر currentTime ذخیره می کند. هنگامی که در متغیر ذخیره شد، تابع fmt.Println، CurrentTime را با استفاده از فرمت خروجی رشته پیش فرض time.Time روی صفحه چاپ می کند.

برنامه را با استفاده از go run با فایل main.go اجرا کنید:

go run main.go

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

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626

خروجی تاریخ و زمان فعلی شما را نشان می دهد که با مثال متفاوت است. علاوه بر این، منطقه زمانی که مشاهده می کنید (-0500 CDT در این خروجی) احتمالاً متفاوت خواهد بود، زیرا time.Now() زمان را در منطقه زمانی محلی برمی گرداند.

همچنین ممکن است متوجه یک مقدار m= در خروجی خود شوید. این مقدار ساعت یکنواخت است و به صورت داخلی توسط Go هنگام اندازه گیری تفاوت در زمان استفاده می شود. ساعت یکنواخت برای جبران هرگونه تغییر احتمالی در تاریخ و زمان ساعت سیستم کامپیوتر در حین اجرای برنامه طراحی شده است. با استفاده از ساعت یکنواخت، یک مقدار time.Now در مقایسه با زمان. اکنون مقدار پنج دقیقه بعد همچنان به نتیجه صحیح ختم می شود (فاصله پنج دقیقه)، حتی اگر ساعت سیستم برای رایانه یک ساعت به جلو تغییر کند. یا در طی آن فاصله پنج دقیقه ای به عقب برگردید. برای کد یا مثال‌های موجود در این آموزش، نیازی به درک کامل آن ندارید، اما اگر می‌خواهید درباره ساعت‌های یکنواخت و نحوه استفاده Go از آن‌ها بیشتر بدانید، بخش ساعت‌های یکنواخت در مستندات بسته زمانی جزئیات بیشتری را ارائه می‌دهد.

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

خوشبختانه، نوع time.Time شامل روش های مختلفی برای به دست آوردن قسمت های خاصی از تاریخ یا ساعت مورد نظر شما است. به عنوان مثال، اگر فقط می‌خواهید بخش سال متغیر currentTime را بدانید، می‌توانید از روش Year استفاده کنید یا ساعت جاری را با استفاده از روش Hour دریافت کنید.

فایل main.go خود را دوباره باز کنید و چند روش time.Time را به خروجی خود اضافه کنید تا ببینید چه چیزی تولید می کنند:

projects/datetime/main.go

...

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
	
	fmt.Println("The year is", currentTime.Year())
	fmt.Println("The month is", currentTime.Month())
	fmt.Println("The day is", currentTime.Day())
	fmt.Println("The hour is", currentTime.Hour())
	fmt.Println("The minute is", currentTime.Hour())
	fmt.Println("The second is", currentTime.Second())
}

سپس با استفاده از go run دوباره برنامه خود را اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626
The year is 2021
The month is August
The day is 15
The hour is 14
The minute is 14
The second is 45

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

اکنون، فایل main.go را دوباره در برنامه خود به‌روزرسانی کنید و خروجی‌های تابع مختلف را با یک فراخوانی تابع به fmt.Printf جایگزین کنید، بنابراین می‌توانید تاریخ و زمان فعلی را در قالبی نزدیک‌تر به آنچه می‌خواهید نمایش دهید چاپ کنید. یک کاربر:

projects/datetime/main.go

...

func main() {
	currentTime := time.Now()
	fmt.Println("The time is", currentTime)
	
	fmt.Printf("%d-%d-%d %d:%d:%d\n",
		currentTime.Year(),
		currentTime.Month(),
		currentTime.Day(),
		currentTime.Hour(),
		currentTime.Hour(),
		currentTime.Second())
}

هنگامی که به روز رسانی های خود را در فایل main.go ذخیره کردید، آن را با استفاده از دستور go run مانند قبل اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626
2021-8-15 14:14:45

این بار ممکن است خروجی شما به چیزی که می‌خواهید نزدیک‌تر باشد، اما هنوز چند چیز وجود دارد که می‌توان در مورد خروجی اصلاح کرد. ماه اکنون دوباره در قالب عددی نمایش داده می‌شود، زیرا قالب fmt.Printf از %d برای نشان دادن زمان استفاده می‌کند. نوع ماه باید از یک عدد استفاده کند نه رشته، اما فقط به صورت تک رقمی نشان داده می‌شود. اگر می‌خواهید دو رقم نمایش داده شود، می‌توانید فرمت fmt.Printf را برای گفتن آن تغییر دهید، اما اگر بخواهید به جای زمان ۲۴ ساعته همانطور که در خروجی بالا نشان داده شده است، یک زمان ۱۲ ساعته را نیز نشان دهید، چطور؟ با استفاده از روش fmt.Printf، شما باید برای محاسبه آن، ریاضی خود را انجام دهید. چاپ تاریخ و زمان با استفاده از fmt.Printf امکان پذیر است، اما همانطور که می بینید، در نهایت می تواند دست و پا گیر شود. با انجام این کار، می‌توانید برای هر قسمتی که می‌خواهید نمایش دهید تعداد زیادی خط داشته باشید، یا باید تعدادی از محاسبات خود را برای تعیین اینکه چه چیزی را نمایش دهید انجام دهید.

در این قسمت برنامه جدیدی برای دریافت زمان فعلی با استفاده از time.Now ایجاد کردید. هنگامی که زمان فعلی را داشتید، سپس از عملکردهای مختلفی مانند سال و ساعت در زمان. نوع زمان برای چاپ اطلاعات مربوط به زمان فعلی استفاده کردید. با این حال، نمایش آن در یک قالب سفارشی شروع به کار زیادی کرد. برای آسان‌تر کردن این نوع کار رایج، بسیاری از زبان‌های برنامه‌نویسی، از جمله Go، روش خاصی را برای قالب‌بندی تاریخ‌ها و زمان‌ها ارائه می‌کنند، مشابه روشی که fmt.Printf می‌تواند برای قالب‌بندی یک رشته استفاده شود.

چاپ و قالب بندی تاریخ های خاص

علاوه بر سال، ساعت و سایر روش‌های مرتبط با داده که نوع time.Time ارائه می‌کند، روشی به نام Format را نیز ارائه می‌کند. متد Format به شما امکان می‌دهد یک رشته طرح‌بندی، شبیه به فرمت fmt.Printf یا fmt.Sprintf ارائه دهید، که به روش Format می‌گوید که چگونه می‌خواهید تاریخ و زمان چاپ شود. در این بخش، خروجی زمانی را که در بخش گذشته اضافه کرده‌اید، تکرار می‌کنید، اما به روشی بسیار مختصرتر با استفاده از روش Format.

با این حال، قبل از استفاده از روش Format، اگر هر بار که برنامه را اجرا می‌کنید تغییری نمی‌کند، بهتر است ببینید که چگونه Format بر خروجی یک تاریخ و زمان تأثیر می‌گذارد. تا به حال، شما زمان فعلی را با استفاده از زمان دریافت می‌کردید. اکنون، بنابراین هر بار که آن را اجرا می‌کردید، عدد متفاوتی نشان داده می‌شد. بسته Go time یک تابع مفید دیگر را ارائه می دهد، تابع time.Date، که به شما امکان می دهد تاریخ و زمان خاصی را برای نمایش زمان تعیین کنید.

برای شروع استفاده از time.Date به جای time.Now در برنامه خود، فایل main.go را دوباره باز کنید و آن را به روز کنید تا جایگزین time.Now با time.Date شود:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
}

پارامترهای تابع time.Date شامل سال، ماه، روز ماه، ساعت، دقیقه و ثانیه از تاریخ و زمانی است که می‌خواهید زمان. زمان برای آن تعیین کنید. اولین پارامتر از دو پارامتر آخر برای نانوثانیه ها محاسبه می شود و آخرین پارامتر منطقه زمانی برای ایجاد زمان است. استفاده از مناطق زمانی خود بعداً در این آموزش پوشش داده شده است.

پس از ذخیره به روز رسانی ها، برنامه خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT

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

سفارشی کردن رشته های تاریخ با استفاده از روش قالب

بسیاری از زبان‌های برنامه‌نویسی دیگر روشی مشابه برای قالب‌بندی تاریخ‌ها و زمان‌ها برای نمایش دارند، اما روشی که Go طرح‌بندی آن فرمت‌ها را می‌سازد ممکن است کمی متفاوت از آنچه شما به آن عادت کرده‌اید، باشد، اگر از آن‌ها در زبان‌های دیگر استفاده کرده باشید. در زبان‌های دیگر، قالب‌بندی تاریخ از سبکی مشابه نحوه عملکرد Printf در Go استفاده می‌کند، با یک کاراکتر % و به دنبال آن یک حرف نشان‌دهنده بخشی از تاریخ یا زمان برای درج. به عنوان مثال، یک سال 4 رقمی ممکن است با %Y نشان داده شود. اما در Go، این بخش‌های تاریخ یا زمان با کاراکترهایی نشان داده می‌شوند که تاریخ خاصی را نشان می‌دهند. برای گنجاندن یک سال 4 رقمی در قالب تاریخ Go، در واقع باید سال 2006 را در خود رشته قرار دهید. مزیت این نوع چیدمان این است که آنچه در کد می بینید در واقع نشان دهنده چیزی است که در خروجی خواهید دید. وقتی بتوانید نمایشی از خروجی خود را مشاهده کنید، بررسی مجدد اینکه قالب شما با آنچه به دنبال آن هستید مطابقت دارد آسان تر می شود و همچنین درک خروجی برنامه را برای سایر توسعه دهندگان بدون اجرای برنامه آسان تر می کند. اول برنامه

تاریخ خاصی که Go برای طرح‌بندی تاریخ و زمان در قالب‌بندی رشته استفاده می‌کند، 01/02 03:04:05 06 -0700 است. اگر به هر جزء تاریخ و زمان نگاه کنید، خواهید دید که برای هر قسمت یک عدد افزایش می یابد. ماه اول در 01 می آید، پس از آن روز ماه در 02، سپس ساعت در 03، دقیقه در 04، دوم در 05، سال در 06 (یا 2006) و، در نهایت، منطقه زمانی در 07. به خاطر سپردن این ترتیب، ایجاد قالب‌های تاریخ و زمان را در آینده آسان‌تر می‌کند. نمونه‌هایی از گزینه‌های موجود برای قالب‌بندی را نیز می‌توانید در اسناد بسته زمانی Go پیدا کنید.

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

فایل main.go را باز کنید و یک تماس جدید fmt.Println اضافه کنید و آن را با تاریخ فرمت شده با استفاده از روش Format به Time ارسال کنید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)

	fmt.Println(theTime.Format("2006-1-2 15:4:5"))
}

اگر به طرح مورد استفاده برای قالب نگاه کنید، خواهید دید که از همان زمان از بالا برای تعیین نحوه قالب بندی تاریخ و زمان استفاده می کند (2 ژانویه 2006). نکته ای که باید به آن توجه کرد این است که ساعت به جای 03 مانند مثال قبلی از 15 استفاده می کند. این نشان می دهد که شما می خواهید ساعت به جای 12 ساعت در قالب 24 ساعته نمایش داده شود.

برای دیدن خروجی از این فرمت جدید، برنامه خود را ذخیره کرده و با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-8-15 14:30:45

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

بسته به تاریخ یا زمانی که نمایش می‌دهید، استفاده از قالبی با طول متغیر مانند فرمتی که هنگام چاپ مستقیم اعداد با آن به پایان رسید، ممکن است برای خود، کاربران یا سایر کدهایی که سعی در خواندن مقدار دارند، خواندن آن دشوار باشد. استفاده از 1 برای قالب ماه باعث می شود که مارس به صورت 3 نمایش داده شود، در حالی که اکتبر از دو کاراکتر استفاده می کند و به صورت 10 نشان داده می شود. اکنون main.go را باز کنید و با طرح بندی ساختارمندتر، یک خط اضافی به برنامه خود اضافه کنید. در این چیدمان، یک پیشوند 0 روی کامپوننت ها قرار دهید و ساعت را برای استفاده از قالب 12 ساعته به روز کنید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)

	fmt.Println(theTime.Format("2006-1-2 15:4:5"))
	fmt.Println(theTime.Format("2006-01-02 03:04:05 pm"))
}

پس از ذخیره کد خود، دوباره برنامه را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-8-15 14:30:45
2021-08-15 02:30:45 pm

خواهید دید که با افزودن یک پیشوند 0 به اعداد در رشته طرح بندی، 8 ماه در خروجی جدید به 08 تبدیل می شود تا با چیدمان مطابقت داشته باشد. ساعت که اکنون در قالب 12 ساعته است، پیشوند 0 خود را نیز دارد. با این حال، در پایان، آنچه در خروجی مشاهده می کنید، فرمتی را که در کد می بینید منعکس می کند، بنابراین در صورت نیاز، تغییر قالب آسان تر است.

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

با استفاده از فرمت از پیش تعریف شده

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

یکی از قالب‌های موجود و اغلب مورد استفاده، فرمت تعریف‌شده در RFC 3339 است. RFC سندی است که برای تعریف نحوه عملکرد استانداردها در اینترنت استفاده می‌شود و RFC‌های دیگر می‌توانند بر روی یکدیگر ایجاد کنند. یک RFC وجود دارد که نحوه عملکرد HTTP را تعریف می کند (RFC 2616)، برای مثال، و دیگرانی که در بالای آن برای تعریف بیشتر HTTP ساخته می شوند. بنابراین، در مورد RFC 3339، RFC یک قالب استاندارد برای استفاده برای مهرهای زمانی در اینترنت تعریف می‌کند. این قالب در سراسر اینترنت شناخته شده و به خوبی پشتیبانی می شود، بنابراین شانس دیدن آن در جای دیگر زیاد است.

هر یک از قالب‌های زمانی از پیش تعریف‌شده در بسته زمانی با یک رشته const به نام قالبی که نشان می‌دهند نشان داده می‌شوند. فرمت RFC 3339 دو فرمت در دسترس دارد، یکی به نام time.RFC3339 و دیگری به نام time.RFC3339Nano. تفاوت فرمت ها در این است که نسخه time.RFC3339Nano شامل نانوثانیه در فرمت است.

اکنون فایل main.go خود را دوباره باز کنید و برنامه خود را به روز کنید تا از فرمت time.RFC3339Nano برای خروجی آن استفاده کنید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

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

برای دیدن خروجی، برنامه خود را با go run دوباره اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-08-15T14:30:45.0000001-05:00

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

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

تجزیه تاریخ و زمان در رشته ها

اغلب هنگام توسعه برنامه‌ها، با تاریخ‌هایی مواجه می‌شوید که به‌عنوان مقادیر رشته‌ای نشان داده می‌شوند که باید به نحوی آن‌ها را تفسیر کنید. گاهی اوقات، شما باید قسمت تاریخ مقدار را بدانید، گاهی اوقات ممکن است نیاز به دانستن بخش زمانی داشته باشید، و برخی دیگر ممکن است به کل مقدار نیاز داشته باشید. بسته Go time علاوه بر استفاده از روش Format برای ایجاد مقادیر رشته ای از مقادیر time.Time، تابع time.Parse را برای تبدیل یک رشته به مقدار time.Time ارائه می دهد. تابع time.Parse شبیه به روش Format عمل می کند، به این صورت که طرح تاریخ و زمان مورد انتظار و همچنین مقدار رشته را به عنوان پارامتر می گیرد.

اکنون فایل main.go را در برنامه خود باز کنید و آن را به روز کنید تا از تابع time.Parse برای تجزیه یک timeString به متغیر time.Time استفاده کنید:

projects/datetime/main.go

...

func main() {
	timeString := "2021-08-15 02:30:45"
	theTime, err := time.Parse("2006-01-02 03:04:05", timeString)
	if err != nil {
		fmt.Println("Could not parse time:", err)
	}
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

برخلاف روش Format، متد time.Parse همچنین در صورتی که مقدار رشته ارسال شده با طرح ارائه شده به عنوان پارامتر اول مطابقت نداشته باشد، مقدار خطای احتمالی را برمی گرداند. اگر به چیدمان استفاده شده نگاه کنید، می بینید که چیدمان داده شده به time.Parse از همان 1 برای ماه، 2 برای روز ماه و غیره استفاده می کند که در متد Format استفاده می شود.

پس از ذخیره به روز رسانی های خود، می توانید برنامه به روز شده خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 02:30:45 +0000 UTC
2021-08-15T02:30:45Z

در این خروجی باید به چند نکته توجه کرد. یکی این که منطقه زمانی که از timeString تجزیه می‌شود از منطقه زمانی پیش‌فرض استفاده می‌کند که یک افست +0 است و به عنوان زمان جهانی هماهنگ (UTC) شناخته می‌شود. از آنجایی که نه مقدار زمان و نه چیدمان شامل منطقه زمانی نمی شود، تابع time.Parse نمی داند که با کدام منطقه زمانی مرتبط شود. اگر زمانی به آن نیاز داشتید، بسته زمانی شامل یک تابع time.ParseInLocation می‌شود تا بتوانید مکان مورد استفاده را ارائه دهید. بخش دیگری که باید به آن توجه کرد در خروجی RFC 3339 است. خروجی از طرح‌بندی نانو RFC3339 استفاده می‌کند، اما خروجی شامل هیچ نانوثانیه‌ای نمی‌شود. این به این دلیل است که تابع time.Parse هیچ نانوثانیه‌ای را تجزیه نمی‌کند، بنابراین مقدار روی پیش‌فرض 0 تنظیم می‌شود. وقتی نانوثانیه‌ها 0 هستند، فرمت time.RFC3339Nano شامل نانوثانیه‌ها در خروجی نمی‌شود.

متد time.Parse همچنین می‌تواند از هر یک از طرح‌بندی‌های زمانی از پیش تعریف‌شده ارائه شده در بسته زمان هنگام تجزیه یک مقدار رشته استفاده کند. برای مشاهده این موضوع در عمل، فایل main.go خود را باز کنید و مقدار timeString را به روز کنید تا با خروجی time.RFC3339Nano قبل از آن مطابقت داشته باشد و پارامتر time.Parse را برای مطابقت به روز کنید:

projects/datetime/main.go

...

func main() {
	timeString := "2021-08-15T14:30:45.0000001-05:00"
	theTime, err := time.Parse(time.RFC3339Nano, timeString)
	if err != nil {
		fmt.Println("Could not parse time:", err)
	}
	fmt.Println("The time is", theTime)
	
	fmt.Println(theTime.Format(time.RFC3339Nano))
}

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

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-08-15T14:30:45.0000001-05:00

این بار، خروجی از روش Format نشان می دهد که time.Parse توانست هم منطقه زمانی و هم نانوثانیه های timeString را تجزیه کند.

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

کار با مناطق زمانی

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

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

اکنون، فایل main.go خود را باز کنید تا برنامه خود را به روز کنید تا از روش UTC در theTime برای برگرداندن نسخه UTC زمان استفاده کنید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	fmt.Println(theTime.Format(time.RFC3339Nano))
	
	utcTime := theTime.UTC()
	fmt.Println("The UTC time is", utcTime)
	fmt.Println(utcTime.Format(time.RFC3339Nano))
}

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

برای دیدن خروجی برنامه، می توانید آن را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-08-15T14:30:45.0000001-05:00
The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC
2021-08-15T19:30:45.0000001Z

خروجی شما بسته به منطقه زمانی محلی شما متفاوت خواهد بود، اما در خروجی بالا، خواهید دید که اولین باری که چاپ می شود در CDT (زمان نوری مرکزی آمریکای شمالی) است که 5- ساعت از UTC فاصله دارد. هنگامی که متد UTC فراخوانی شد و زمان UTC چاپ شد، می توانید ببینید که ساعت در زمان از 14 به 19 می رسد، زیرا تبدیل زمان به UTC پنج ساعت اضافه می کند.

همچنین می‌توان یک زمان UTC را به زمان محلی با استفاده از روش محلی در یک زمان. زمان به همان روش تبدیل کرد. فایل main.go خود را دوباره باز کنید و آن را به روز کنید تا یک تماس به روش محلی در utcTime اضافه کنید تا آن را به منطقه زمانی محلی خود تبدیل کنید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
	fmt.Println("The time is", theTime)
	fmt.Println(theTime.Format(time.RFC3339Nano))
	
	utcTime := theTime.UTC()
	fmt.Println("The UTC time is", utcTime)
	fmt.Println(utcTime.Format(time.RFC3339Nano))

	localTime := utcTime.Local()
	fmt.Println("The Local time is", localTime)
	fmt.Println(localTime.Format(time.RFC3339Nano))
}

هنگامی که فایل شما ذخیره شد، برنامه خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-08-15T14:30:45.0000001-05:00
The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC
2021-08-15T19:30:45.0000001Z
The Local time is 2021-08-15 14:30:45.0000001 -0500 CDT
2021-08-15T14:30:45.0000001-05:00

خواهید دید که زمان UTC دوباره به منطقه زمانی محلی شما تبدیل شده است. در خروجی بالا، تبدیل UTC به CDT به این معنی است که پنج ساعت از UTC کم شده است و ساعت را از 19 به 14 تغییر می دهد.

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

هنگامی که مقادیر تاریخ و زمان خود را در دسترس قرار دادید، تعدادی ویژگی اضافی وجود دارد که بسته Go time ارائه می دهد که می تواند در برنامه های شما مفید باشد. یکی از این ویژگی ها تعیین این است که آیا زمان معین قبل یا بعد از دیگری است.

مقایسه دو بار

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

بسته زمان دو روش برای آسان‌تر کردن این مقایسه‌ها ارائه می‌کند: روش‌های قبل و بعد، که در نوع time.Time در دسترس هستند. این روش‌ها هر دو یک مقدار زمانی واحد را می‌پذیرند و بسته به اینکه زمانی که فراخوانی می‌شوند قبل یا بعد از زمان ارائه شده باشد، true یا false را برمی‌گردانند.

برای مشاهده نمونه ای از این توابع در عمل، فایل main.go خود را باز کنید و آن را به روز کنید تا شامل دو تاریخ مختلف باشد، سپس از قبل و بعد برای مقایسه آن تاریخ ها برای دیدن خروجی استفاده کنید:

projects/datetime/main.go

...

func main() {
	firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The first time is", firstTime)

	secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
	fmt.Println("The second time is", secondTime)

	fmt.Println("First time before second?", firstTime.Before(secondTime))
	fmt.Println("First time after second?", firstTime.After(secondTime))

	fmt.Println("Second time before first?", secondTime.Before(firstTime))
	fmt.Println("Second time after first?", secondTime.After(firstTime))
}

هنگامی که فایل خود را به روز کردید، آن را ذخیره کرده و با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The first time is 2021-08-15 14:30:45.0000001 +0000 UTC
The second time is 2021-12-25 16:40:55.0000002 +0000 UTC
First time before second? true
First time after second? false
Second time before first? false
Second time after first? true

از آنجایی که کد از تاریخ های صریح در منطقه زمانی UTC استفاده می کند، خروجی شما باید با خروجی بالا مطابقت داشته باشد. خواهید دید که هنگام استفاده از روش Before در firstTime و ارائه آن secondTime برای مقایسه، این درست است که 2021-08-15 قبل از 2021-12-25 است. هنگام استفاده از روش After از firstTime و ارائه secondTime، اشتباه است که 2021-08-15 بعد از 2021-12-25 باشد. تغییر ترتیب فراخوانی متدها در secondTime، همانطور که انتظار می رود، نتایج مخالف را نشان می دهد.

روش دیگر برای مقایسه دو تاریخ و زمان با بسته زمانی، روش Sub است. متد Sub یک تاریخ را از تاریخ دیگر کم می کند و با استفاده از نوع جدیدی به نام time.Duration مقداری را برمی گرداند. بر خلاف یک مقدار time.Time، که یک نقطه مطلق در زمان را نشان می دهد، یک مقدار time.Duration نشان دهنده تفاوت در زمان است. به عنوان مثال، “در یک ساعت” مدت زمان خواهد بود زیرا به معنای چیزی متفاوت بر اساس زمان فعلی روز است، اما “در ظهر” یک زمان خاص و مطلق را نشان می دهد. Go از زمان استفاده می‌کند. نوع مدت زمان در تعدادی مکان، مانند زمانی که می‌خواهید مشخص کنید که یک تابع چه مدت باید قبل از بازگشت خطا منتظر بماند یا در اینجا، جایی که باید بدانید بین یک زمان و زمان دیگر چقدر زمان وجود دارد، استفاده می‌کند.

اکنون فایل main.go خود را به روز کنید تا از روش Sub در مقادیر firstTime و secondTime استفاده کنید و نتایج را چاپ کنید:

projects/datetime/main.go

...

func main() {
	firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The first time is", firstTime)

	secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
	fmt.Println("The second time is", secondTime)

	fmt.Println("Duration between first and second time is", firstTime.Sub(secondTime))
	fmt.Println("Duration between second and first time is", secondTime.Sub(firstTime))

فایل خود را ذخیره کنید و سپس با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The first time is 2021-08-15 14:30:45.0000001 +0000 UTC
The second time is 2021-12-25 16:40:55.0000002 +0000 UTC
Duration between first and second time is -3170h10m10.0000001s
Duration between second and first time is 3170h10m10.0000001s

خروجی بالا می گوید 3170 ساعت، 10 دقیقه، 10 ثانیه و 100 نانوثانیه بین این دو تاریخ وجود دارد و چند نکته در مورد خروجی وجود دارد. اولین مورد این است که مدت زمان بین بار اول و دوم یک مقدار منفی است. این می‌گوید که زمان دوم بعد از زمان اول است و شبیه به زمانی خواهد بود که 5 را از 0 کم کنید و 5- را دریافت کنید. دومین موردی که باید به آن توجه کرد این است که بزرگترین واحد اندازه گیری مدت زمان یک ساعت است، بنابراین آن را به روز یا ماه تقسیم نمی کند. از آنجایی که تعداد روزهای یک ماه یکسان نیست و یک “روز” می تواند در طول سوئیچ برای ساعت تابستانی معنای متفاوتی داشته باشد، یک ساعت دقیق ترین اندازه گیری است که نوسان ندارد.

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

اضافه یا تفریق زمان

هنگام نوشتن یک برنامه، یک عملیات رایج با استفاده از تاریخ و زمان، تعیین زمان گذشته یا آینده بر اساس زمان دیگر است. می‌توان از آن برای عملکرد استفاده کرد، مانند تعیین زمان تمدید اشتراک بعدی، یا اینکه مدت زمان مشخصی از بررسی مقداری گذشته است. در هر صورت، بسته Go time راهی برای مدیریت آن ارائه می دهد. برای پیدا کردن تاریخ دیگری بر اساس تاریخی که قبلاً می‌دانید، باید بتوانید زمان خود را تعیین کنید. مقادیر مدت زمان.

ایجاد یک مقدار time.Duration شبیه نحوه نوشتن مدت زمان روی کاغذ است، فقط با ضرب واحد زمان. به عنوان مثال، برای ایجاد زمان. مدت زمان برای نشان دادن یک ساعت، باید آن را با استفاده از مقدار time.Hour ضرب در تعداد ساعت‌هایی که می‌خواهید زمان را نشان دهید، تعریف کنید.

oneHour := 1 * time.Hour
twoHours := 2 * time.Hour
tenHours := 10 * time.Hour

اعلان واحدهای زمانی کوچکتر به روشی مشابه انجام می شود، به جز استفاده از time.minute، time.second و غیره:

tenMinutes := 10 * time.Minute
fiveSeconds := 5 * time.Second

همچنین می توان یک مدت زمان را به مدت زمان دیگر اضافه کرد تا مجموع مدت زمان ها بدست آید. برای اینکه این را در عمل ببینید، فایل main.go خود را باز کنید و آن را به روز کنید تا یک متغیر toAdd duration را اعلام کنید و مدت زمان های مختلف را به آن اضافه کنید:

projects/datetime/main.go

...

func main() {
	toAdd := 1 * time.Hour
	fmt.Println("1:", toAdd)

	toAdd += 1 * time.Minute
	fmt.Println("2:", toAdd)

	toAdd += 1 * time.Second
	fmt.Println("3:", toAdd)
}

پس از اتمام به روز رسانی، فایل را ذخیره کنید و برنامه خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

1: 1h0m0s
2: 1h1m0s
3: 1h1m1s

هنگامی که به خروجی نگاه می کنید، خواهید دید که اولین مدت چاپ یک ساعت است که مطابق با زمان 1 * ساعت در کد شما است. در مرحله بعد، 1 * time.Minute را به مقدار toAdd اضافه کردید، که به عنوان مقدار یک ساعت، یک دقیقه نشان داده می شود. در نهایت، 1 * time.Second را به toAdd اضافه کردید، که منجر به مقدار زمان. مدت زمان یک ساعت، یک دقیقه و یک ثانیه شد.

همچنین می توان با اضافه کردن مدت زمان ها در یک عبارت، یا کم کردن مدت زمان از دیگری را ترکیب کرد:

oneHourOneMinute := 1 * time.Hour + 1 * time.Minute
tenMinutes := 1 * time.Hour - 50 * time.Minute

بعد، فایل main.go خود را باز کنید و برنامه خود را به روز کنید تا از ترکیبی مانند این برای کم کردن یک دقیقه و یک ثانیه از toAdd استفاده کنید:

projects/datetime/main.go

...

func main() {
	
	...
	
	toAdd += 1 * time.Second
	fmt.Println("3:", toAdd)
	
	toAdd -= 1*time.Minute + 1*time.Second
	fmt.Println("4:", toAdd)
}

پس از ذخیره کد خود، می توانید برنامه را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

1: 1h0m0s
2: 1h1m0s
3: 1h1m1s
4: 1h0m0s

خط چهارم جدید اضافه شده به خروجی کد جدیدی را که برای تفریق مجموع 1 * time.Minute و 1 * time اضافه کرده اید نشان می دهد.

استفاده از این مدت زمان‌ها که با متد Add of the time.Time جفت شده‌اند، به شما این امکان را می‌دهد که یک مقدار زمانی را که قبلاً دارید انتخاب کنید و زمان را در نقطه دلخواه دیگری قبل یا بعد از آن زمان تعیین کنید. برای مشاهده نمونه ای از این در حال اجرا، فایل main.go خود را باز کنید و آن را به روز کنید تا مقدار toAdd را روی 24 ساعت یا 24 * time.Hour تنظیم کنید. سپس، از روش افزودن روی مقدار time.Time استفاده کنید تا ببینید 24 ساعت پس از آن نقطه چه زمانی خواهد بود:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The time is", theTime)

	toAdd := 24 * time.Hour
	fmt.Println("Adding", toAdd)

	newTime := theTime.Add(toAdd)
	fmt.Println("The new time is", newTime)
}

پس از ذخیره فایل خود، برنامه خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 +0000 UTC
Adding 24h0m0s
The new time is 2021-08-16 14:30:45.0000001 +0000 UTC

با نگاهی به خروجی، خواهید دید که افزودن 24 ساعت به 2021-08-15 منجر به تاریخ جدید 2021-08-16 می شود.

برای کم کردن زمان، از روش افزودن نیز استفاده می‌کنید که کمی غیرمعمول است. از آنجایی که از روش Sub برای بدست آوردن اختلاف زمان بین دو تاریخ استفاده می شود، با استفاده از Add با مقدار منفی، زمان را از مقدار time.Time کم می کنید.

یک بار دیگر، برای مشاهده این مورد در برنامه خود، فایل main.go خود را باز کرده و آن را به روز کنید تا مقدار 24 ساعته toAdd را به مقدار منفی تغییر دهید:

projects/datetime/main.go

...

func main() {
	theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
	fmt.Println("The time is", theTime)

	toAdd := -24 * time.Hour
	fmt.Println("Adding", toAdd)

	newTime := theTime.Add(toAdd)
	fmt.Println("The new time is", newTime)
}

پس از ذخیره فایل خود، یک بار دیگر برنامه خود را با استفاده از go run اجرا کنید:

go run main.go

خروجی شبیه به این خواهد بود:

 

Output

The time is 2021-08-15 14:30:45.0000001 +0000 UTC
Adding -24h0m0s
The new time is 2021-08-14 14:30:45.0000001 +0000 UTC

این بار در خروجی خواهید دید که به جای اضافه کردن 24 ساعت به زمان اصلی، تاریخ جدید 24 ساعت قبل از زمان اصلی است.

در این بخش از time.Hour، time.Minute و time.Second برای ایجاد مقادیر time.Duration در درجات مختلف استفاده کردید. شما همچنین از مقادیر time.Duration با متد Add استفاده کردید تا یک مقدار time.Time جدید قبل و بعد از مقدار اصلی بدست آورید. با ترکیب زمان. اکنون، روش افزودن، و روش های قبل یا بعد، به عملکرد قدرتمند تاریخ و زمان برای برنامه های خود دسترسی خواهید داشت.

نتیجه

در این آموزش، شما از time.Now برای بازیابی یک مقدار time.Time برای زمان محلی فعلی در رایانه خود استفاده کردید، سپس از سال، ماه، ساعت و روش های دیگر برای دسترسی به اطلاعات خاصی در مورد آن زمان استفاده کردید. سپس، از روش Format برای چاپ زمان با استفاده از یک قالب سفارشی و یک قالب از پیش تعریف شده استفاده کردید. در مرحله بعد، از تابع time.Parse برای تفسیر مقدار رشته با زمان در آن و استخراج مقدار زمان از آن استفاده کردید. هنگامی که مقدار زمان را داشتید، از روش های UTC و Local برای ترجمه زمان بین UTC و منطقه زمانی محلی خود استفاده کردید. پس از آن، قبل از استفاده از روش افزودن برای یافتن زمان نسبت به مقدار زمانی متفاوت، از روش Sub برای بدست آوردن مدت زمان بین دو زمان مختلف استفاده کردید.

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

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:VPS یا سرور مجازیآموزش برنامه GOاتصال به سرور مجازی ویندوزبرنامه Goخرید سرور مجازیراه اندازی اولیه سرورسرور مجازیسفارشی کردن رشته های تاریخ

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه راه اندازی پلتفرم Eclipse Theia Cloud IDE در vpsgol Kubernetes

ورود به سایت

معرفی

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

Eclipse Theia یک IDE ابری توسعه پذیر است که روی یک سرور راه دور اجرا می شود و از یک مرورگر وب قابل دسترسی است. از نظر بصری، به گونه‌ای طراحی شده است که شبیه به Microsoft Visual Studio Code به نظر برسد و رفتاری مشابه داشته باشد، به این معنی که از بسیاری از زبان‌های برنامه‌نویسی پشتیبانی می‌کند، طرح‌بندی انعطاف‌پذیری دارد و ترمینال یکپارچه دارد. آنچه Eclipse Theia را از سایر نرم افزارهای Cloud IDE جدا می کند، توسعه پذیری آن است. می توان آن را با استفاده از پسوندهای سفارشی تغییر داد، که به شما امکان می دهد یک IDE ابری متناسب با نیازهای خود ایجاد کنید.

در این آموزش، شما نسخه پیش‌فرض پلت‌فرم Eclipse Theia ابری IDE را در خوشه vpsgol Kubernetes خود راه‌اندازی می‌کنید و آن را در دامنه خود، با گواهی‌های Let’s Encrypt ایمن می‌کنید و از بازدیدکننده برای احراز هویت می‌خواهد. در پایان، Eclipse Theia را خواهید داشت که روی خوشه Kubernetes شما از طریق HTTPS در دسترس است و بازدیدکننده را ملزم به ورود به سیستم می‌کند.

پیش نیازها

  • یک خوشه vpsgol Kubernetes با اتصال شما به عنوان پیش فرض kubectl پیکربندی شده است. دستورالعمل های مربوط به نحوه پیکربندی kubectl در مرحله اتصال به خوشه خود هنگام ایجاد خوشه نشان داده می شود.
  • مدیریت بسته Helm 3 بر روی دستگاه محلی شما نصب شده است.
  • Nginx Ingress Controller با استفاده از Helm برای استفاده از ExternalDNS با منابع Ingress بر روی خوشه شما نصب شده است.
  • یک نام دامنه کاملاً ثبت شده این آموزش از theia.your_domain در سرتاسر استفاده خواهد کرد. می توانید یک نام دامنه را در Namecheap خریداری کنید، یک نام دامنه را به صورت رایگان در Freenom دریافت کنید، یا از ثبت کننده دامنه انتخابی خود استفاده کنید.

مرحله 1 – نصب و نمایش Eclipse Theia

برای شروع، Eclipse Theia را در خوشه vpsgol Kubernetes خود نصب خواهید کرد. سپس با استفاده از Nginx Ingress آن را در دامنه مورد نظر خود در معرض دید قرار خواهید داد.

از آنجایی که شما دو نمونه استقرار و یک منبع را به عنوان بخشی از پیش نیازها ایجاد کردید، می توانید آزادانه آنها را با اجرای دستورات زیر حذف کنید:

kubectl delete -f hello-kubernetes-ingress.yaml

kubectl delete -f hello-kubernetes-first.yaml

kubectl delete -f hello-kubernetes-second.yaml

برای این آموزش، پیکربندی استقرار را در دستگاه محلی خود در فایلی به نام eclipse-theia.yaml ذخیره خواهید کرد. با استفاده از دستور زیر آن را ایجاد کنید:

nano eclipse-theia.yaml

خطوط زیر را به فایل اضافه کنید:

eclipse-theia.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: theia
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: theia-next
  namespace: theia
spec:
  ingressClassName: nginx
  rules:
  - host: theia.your_domain
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: theia-next
            port:
              number: 80
---
apiVersion: v1
kind: Service
metadata:
 name: theia-next
 namespace: theia
spec:
 ports:
 - port: 80
   targetPort: 3000
 selector:
   app: theia-next
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: theia-next
  name: theia-next
  namespace: theia
spec:
  selector:
    matchLabels:
      app: theia-next
  replicas: 1
  template:
    metadata:
      labels:
        app: theia-next
    spec:
      containers:
      - image: francoisvans/theia-docker-test
        imagePullPolicy: Always
        name: theia-next
        ports:
        - containerPort: 3000

این پیکربندی یک فضای نام، یک استقرار، یک سرویس و یک ورودی را تعریف می کند. فضای نام تیا نامیده می شود و شامل تمام اشیای Kubernetes مربوط به Eclipse Theia است که از بقیه خوشه جدا شده اند. استقرار شامل یک نمونه از تصویر Theia Docker است که پورت 3000 روی کانتینر قرار دارد. این سرویس به دنبال Deployment می‌گردد و پورت کانتینر را به پورت HTTP معمولی 80 تغییر می‌دهد و به Eclipse Theia اجازه دسترسی درون خوشه‌ای را می‌دهد.

Ingress حاوی قانونی برای ارائه سرویس در پورت 80 به صورت خارجی در دامنه مورد نظر شما است. در حاشیه نویسی آن، شما مشخص می کنید که Nginx Ingress Controller باید برای پردازش درخواست استفاده شود. به یاد داشته باشید که دامنه مورد نظر خود را که به Load Balancer کلاستر خود اشاره کرده اید جایگزین theia.your_domain کنید، سپس فایل را ذخیره کرده و ببندید.

فایل را ذخیره کرده و از آن خارج شوید.

سپس با اجرای دستور زیر پیکربندی را در Kubernetes ایجاد کنید:

kubectl apply -f eclipse-theia.yaml

خروجی شبیه به این خواهد بود:

 

Output

namespace/theia created
ingress.networking.k8s.io/theia-next created
service/theia-next created
deployment.apps/theia-next created

می‌توانید با اجرای زیر، ایجاد غلاف Eclipse Theia را تماشا کنید:

kubectl get pods -w -n theia

خروجی به شکل زیر خواهد بود:

 

Output

NAME                          READY   STATUS    RESTARTS   AGE
theia-next-6f6b98dd4f-qknhb   1/1     Running   0          2m30s

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

در مرورگر خود به دامنه خود بروید. رابط کاربری گرافیکی ویرایشگر Eclipse Theia پیش‌فرض را خواهید دید:

 

شما Eclipse Theia را در خوشه vpsgol Kubernetes خود مستقر کرده اید و با یک Ingress آن را در دامنه مورد نظر خود قرار داده اید. در مرحله بعد، با فعال کردن احراز هویت ورود، دسترسی به استقرار Eclipse Theia خود را ایمن خواهید کرد.

مرحله 2 – فعال کردن احراز هویت ورود به سیستم برای دامنه شما

در این مرحله، احراز هویت نام کاربری و رمز عبور را برای استقرار Eclipse Theia خود فعال می‌کنید. ابتدا با تنظیم لیستی از ترکیبات ورود معتبر با استفاده از ابزار htpasswd به این مهم دست خواهید یافت. سپس، یک راز Kubernetes حاوی آن لیست ایجاد می‌کنید و Ingress را برای احراز هویت بازدیدکنندگان بر اساس آن پیکربندی می‌کنید. در پایان، دامنه شما تنها زمانی قابل دسترسی خواهد بود که بازدیدکننده یک ترکیب نام کاربری و رمز عبور معتبر وارد کند. این امر از دسترسی مهمانان و سایر بازدیدکنندگان ناخواسته به Eclipse Theia جلوگیری می کند.

ابزار htpasswd از وب سرور آپاچی می آید و برای ایجاد فایل هایی استفاده می شود که لیست هایی از ترکیبات ورود را ذخیره می کنند. فرمت فایل‌های htpasswd یک نام کاربری: ترکیب hashed_password در هر خط است، که فرمتی است که Nginx Ingress Controller انتظار دارد لیست با آن مطابقت داشته باشد.

ابتدا حافظه پنهان بسته منیجر را به روز کنید:

sudo apt update

سپس htpasswd را با اجرای دستور زیر بر روی سیستم خود نصب کنید:

sudo apt install apache2-utils -y

شما لیست را در فایلی به نام auth ذخیره خواهید کرد. آن را با اجرا ایجاد کنید:

touch auth

این فایل باید auth نامیده شود زیرا کنترلر ورودی Nginx انتظار دارد که رمز حاوی کلیدی به نام data.auth باشد. اگر از دست رفته باشد، کنترل‌کننده وضعیت HTTP 503 Service Unavailable را برمی‌گرداند.

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

htpasswd auth username

به یاد داشته باشید که نام کاربری مورد نظر خود را جایگزین نام کاربری کنید. از شما یک رمز عبور درخواست می شود و این ترکیب به فایل auth اضافه می شود. می توانید این دستور را برای هر تعداد کاربر که می خواهید اضافه کنید تکرار کنید.

پس از اتمام کار، با اجرای دستور زیر یک راز جدید در Kubernetes با محتویات فایل ایجاد کنید:

kubectl create secret generic theia-basic-auth –from-file=auth -n theia

شما می توانید راز را با:

kubectl get secret theia-basic-auth -o yaml -n theia

خروجی به صورت زیر خواهد بود:

 

Output

apiVersion: v1
data:
  auth: ...
kind: Secret
metadata:
  creationTimestamp: "2021-12-31T17:16:29Z"
  name: theia-basic-auth
  namespace: theia
  resourceVersion: "32437"
  uid: 47461e23-e281-411b-acfd-cea82fcde41b
type: Opaque

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

nano eclipse-theia.yaml

خطوط هایلایت شده را به فایل خود اضافه کنید:

eclipse-theia.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: theia
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: theia-next
  namespace: theia
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: theia-basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Eclipse Theia'
spec:
  ingressClassName: nginx
  rules:
  - host: theia.your_domain
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: theia-next
            port:
              number: 80
...

ابتدا در حاشیه نویسی auth-type مشخص می کنید که نوع احراز هویت اولیه است. این بدان معنی است که Nginx از کاربر می خواهد که نام کاربری و رمز عبور را وارد کند. سپس، در auth-secret، مشخص می‌کنید که راز حاوی لیست ترکیبات معتبر theia-basic-auth است که به تازگی ایجاد کرده‌اید. حاشیه نویسی قلمرو اعتبار باقی مانده پیامی را مشخص می کند که به عنوان توضیحی در مورد اینکه چرا احراز هویت لازم است به کاربر نشان داده می شود. می توانید پیام موجود در این قسمت را به دلخواه تغییر دهید.

ذخیره کنید و فایل را ببندید.

برای انتشار تغییرات در کلاستر خود، دستور زیر را اجرا کنید:

kubectl apply -f eclipse-theia.yaml

خروجی را خواهید دید:

 

Output

namespace/theia unchanged
ingress.networking.k8s.io/theia-next configured
service/theia-next unchanged
deployment.apps/theia-next unchanged

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

شما احراز هویت اولیه ورود به سیستم را در Ingress خود با پیکربندی آن برای استفاده از رمز حاوی ترکیب نام کاربری و رمز عبور هش شده فعال کرده اید. در مرحله بعدی، با افزودن گواهی‌های TLS، دسترسی بیشتری را ایمن می‌کنید تا ترافیک بین شما و استقرار Eclipse Theia رمزگذاری شده باقی بماند.

مرحله 3 – اعمال مجوزهای HTTPS Let’s Encrypt

در مرحله بعد، نصب Eclipse Theia خود را با اعمال گواهینامه های Let’s Encrypt در Ingress خود، که Cert-Manager به طور خودکار ارائه می کند، ایمن می کنید. پس از تکمیل این مرحله، نصب Eclipse Theia شما از طریق HTTPS قابل دسترسی خواهد بود.

برای ویرایش eclipse-theia.yaml را باز کنید:

nano eclipse-theia.yaml

خطوط هایلایت شده را به فایل خود اضافه کنید، مطمئن شوید که دامنه جای جای خود را جایگزین کنید:

eclipse-theia.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: theia
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: theia-next
  namespace: theia
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: theia-basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Eclipse Theia'
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - theia.your_domain
    secretName: theia-prod
  ingressClassName: nginx
  rules:
  - host: theia.your_domain
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: theia-next
            port:
              number: 80
...

ابتدا، letsencrypt-prod ClusterIssuer را که ایجاد کرده اید به عنوان بخشی از پیش نیازها به عنوان صادرکننده مشخص می کنید که برای ارائه گواهینامه برای این ورود استفاده می شود. سپس، در بخش tls، دامنه دقیقی را که باید ایمن شود، و همچنین نامی برای رازی که این گواهینامه ها را نگه می دارد، مشخص می کنید.

فایل را ذخیره کرده و از آن خارج شوید.

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

kubectl apply -f eclipse-theia.yaml

خروجی به صورت زیر خواهد بود:

 

Output

namespace/theia unchanged
ingress.networking.k8s.io/theia-next configured
service/theia-next unchanged
deployment.apps/theia-next unchanged

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

kubectl describe certificate theia-prod -n theia

وقتی تمام شد، انتهای خروجی شبیه به این خواهد بود:

 

Output

...
Events:
  Type    Reason        Age   From          Message
  ----    ------        ----  ----          -------
  Normal  GeneratedKey  42m   cert-manager  Generated a new private key
  Normal  Requested     42m   cert-manager  Created new CertificateRequest resource "theia-prod-3785736528"
  Normal  Issued        42m   cert-manager  Certificate issued successfully

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

شما Ingress را برای استفاده از گواهی‌های Let’s Encrypt پیکربندی کرده‌اید، بنابراین استقرار Eclipse Theia را ایمن‌تر می‌کنید. اکنون می توانید رابط کاربری پیش فرض Eclipse Theia را بررسی کنید.

مرحله 4 – استفاده از رابط Eclipse Theia

در این بخش، برخی از ویژگی های رابط Eclipse Theia را بررسی خواهید کرد.

در سمت چپ IDE، یک ردیف عمودی از چهار دکمه وجود دارد که متداول‌ترین ویژگی‌های مورد استفاده را در یک پانل کناری باز می‌کند.

این نوار قابل تنظیم است، بنابراین می توانید این نماها را به ترتیب دیگری منتقل کنید یا آنها را از نوار حذف کنید. به طور پیش فرض، اولین نمای پانل Explorer را باز می کند که ناوبری درخت مانند ساختار پروژه را ارائه می دهد. می‌توانید پوشه‌ها و فایل‌های خود را در اینجا مدیریت کنید—در صورت لزوم آنها را ایجاد، حذف، جابجا کنید و نام آنها را تغییر دهید.

پس از ایجاد یک فایل جدید از طریق منوی File، یک فایل خالی را خواهید دید که در یک تب جدید باز می شود. پس از ذخیره، می توانید نام فایل را در پانل کناری Explorer مشاهده کنید. برای ایجاد پوشه، روی نوار کناری Explorer راست کلیک کرده و روی New Folder کلیک کنید. می‌توانید یک پوشه را با کلیک کردن روی نام آن و همچنین کشیدن و رها کردن فایل‌ها و پوشه‌ها به قسمت‌های بالای سلسله مراتب گسترش دهید تا آنها را به مکان جدیدی منتقل کنید.

گزینه بعدی دسترسی به قابلیت جستجو و جایگزینی را فراهم می کند. به دنبال آن، مورد بعدی نمایی از سیستم های کنترل منبعی را که ممکن است از آنها استفاده می کنید، مانند Git ارائه می دهد.

نمای بعدی گزینه debugger است که تمام اقدامات رایج برای رفع اشکال در پنل را ارائه می دهد. می توانید پیکربندی های اشکال زدایی را در فایل launch.json ذخیره کنید.

گزینه نهایی به شما امکان می دهد برنامه های افزودنی را مشاهده و نصب کنید:

بخش مرکزی رابط کاربری گرافیکی ویرایشگر شما است که می توانید آن را با برگه هایی برای ویرایش کد خود جدا کنید. می توانید نمای ویرایش خود را به یک سیستم شبکه ای یا به فایل های کنار هم تغییر دهید. مانند همه IDE های مدرن، Eclipse Theia از برجسته سازی نحو برای کد شما پشتیبانی می کند.

بخش مرکزی رابط کاربری گرافیکی ویرایشگر شما است که می توانید آن را با برگه هایی برای ویرایش کد خود جدا کنید. می توانید نمای ویرایش خود را به یک سیستم شبکه ای یا به فایل های کنار هم تغییر دهید. مانند همه IDE های مدرن، Eclipse Theia از برجسته سازی نحو برای کد شما پشتیبانی می کند.

اگر می خواهید استقرار Eclipse Theia را در کلاستر خود از بین ببرید، دستور زیر را اجرا کنید:

kubectl delete -f eclipse-theia.yaml

شما یک نمای کلی سطح بالا از رابط Eclipse Theia را بررسی کرده اید و برخی از متداول ترین ویژگی های مورد استفاده را مرور کرده اید.

نتیجه

اکنون Eclipse Theia، یک IDE ابری همه کاره، را روی خوشه vpsgol Kubernetes خود نصب کرده اید. شما آن را با یک گواهی رایگان Let’s Encrypt TLS ایمن کرده اید و نمونه ای را برای نیاز به ورود از بازدیدکننده تنظیم کرده اید. می توانید روی کد منبع و اسناد خود به صورت جداگانه کار کنید یا با تیم خود همکاری کنید.

 

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:ایجاد سرور مجازیخرید سرور مجازیخرید سرور مجازی فرانسهراه اندازی سرور مجازیسرور مجازینحوه راه اندازی پلتفرم Eclipse Theia Cloud IDEنصب Eclipse Theia

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه ایجاد یک سرور Minecraft در اوبونتو 18.04

ورود به سایت

معرفی

Minecraft یک بازی ویدیویی محبوب sandbox است. این برنامه که در ابتدا در سال 2009 منتشر شد، به بازیکنان اجازه می‌دهد در دنیایی سه بعدی بسازند، بسازند، بسازند و زنده بمانند. از اوایل سال 2022، این بازی پرفروش ترین بازی ویدیویی تمام دوران بود. در این آموزش شما سرور Minecraft خود را ایجاد می کنید تا شما و دوستانتان با هم بازی کنید. به طور خاص، شما بسته های نرم افزاری لازم را برای اجرای Minecraft نصب می کنید، سرور را برای اجرا پیکربندی می کنید و سپس بازی را اجرا می کنید.

متناوبا، می‌توانید سرور DigitalOcean’s One-Click Minecraft: Java Edition را به‌عنوان مسیر نصب دیگری بررسی کنید.

پیش نیازها

برای پیروی از این راهنما، شما نیاز دارید:

  • یک سرور با نصب جدید اوبونتو 18.04، یک کاربر غیر ریشه با امتیازات sudo و SSH فعال. شما می توانید این راهنما را برای مقداردهی اولیه سرور خود دنبال کنید و این مراحل را کامل کنید. Minecraft می تواند منابع فشرده ای داشته باشد، بنابراین هنگام انتخاب اندازه سرور خود این را در نظر داشته باشید. اگر از DigitalOcean استفاده می کنید و به منابع بیشتری نیاز دارید، همیشه می توانید اندازه Droplet خود را تغییر دهید تا CPU و RAM بیشتری اضافه کنید.
  • یک کپی از Minecraft Java Edition که روی یک دستگاه Mac، Windows یا Linux محلی نصب شده است.

مرحله 1 – بسته های نرم افزاری لازم را نصب کرده و فایروال را پیکربندی کنید

با شروع اولیه سرور، اولین قدم شما نصب جاوا است. برای اجرای Minecraft به آن نیاز دارید. به طور پیش‌فرض، اوبونتو 18.04 نسخه جدید جاوا را برای اجرای جدیدترین نسخه‌های Minecraft ارائه نمی‌کند. خوشبختانه، نگهبانان شخص ثالثی وجود دارند که به ساخت بسته‌های جاوای جدیدتر برای نسخه‌های قدیمی‌تر اوبونتو ادامه می‌دهند و می‌توانید با افزودن PPA یا آرشیو بسته‌های شخصی آن‌ها به فهرست منابع بسته خود، آن‌ها را نصب کنید. با دستور زیر می توانید این کار را انجام دهید:

sudo add-apt-repository ppa:openjdk-r/ppa

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

sudo apt update

در نهایت، OpenJDK نسخه 17 جاوا، به طور خاص JRE هدلس را نصب کنید. این نسخه حداقلی از جاوا است که پشتیبانی از برنامه های رابط کاربری گرافیکی را حذف می کند. این آن را برای اجرای برنامه های جاوا بر روی سرور ایده آل می کند:

sudo apt install openjdk-17-jre-headless

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

sudo apt install screen

اکنون که بسته‌ها را نصب کرده‌اید، باید فایروال را فعال کنیم تا ترافیک به سرور Minecraft ما وارد شود. در راه اندازی اولیه سرور که انجام دادید، فقط به ترافیک ssh اجازه دادید. اکنون باید اجازه دهید که ترافیک از طریق پورت 25565 وارد شود، که پورت پیش فرضی است که Minecraft برای اجازه دادن به اتصالات استفاده می کند. در برخی موارد ufw از قوانین ترافیکی نام‌گذاری شده استفاده می‌کند، مانند ssh، که همیشه به طور پیش‌فرض از پورت 22 استفاده می‌کند، اما در موارد کمتر رایج مانند این، شماره پورت را به صورت دستی مشخص می‌کنیم. با اجرای دستور زیر قانون فایروال لازم را اضافه کنید:

sudo ufw allow 25565

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

مرحله 2 – دانلود آخرین نسخه Minecraft

اکنون باید نسخه فعلی سرور Minecraft را دانلود کنید. می‌توانید این کار را با رفتن به وب‌سایت Minecraft و کپی کردن پیوندی که می‌گوید دانلود minecraft_server.X.X.X.jar انجام دهید، جایی که Xها آخرین نسخه سرور هستند.

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

wget https://launcher.mojang.com/v1/objects/125e5adf40c659fd3bce3e66e67a16bb49ecc1b9/server.jar

برنامه سرور به عنوان server.jar دانلود می شود. اگر نیاز به مدیریت نسخه‌های Minecraft دارید، یا اگر می‌خواهید سرور Minecraft خود را ارتقا دهید، ممکن است مفید باشد که server.jar دانلود شده را به minecraft_server_1.18.1.jar تغییر نام دهید و اعداد نسخه برجسته شده را با نسخه‌ای که تازه دانلود کرده‌اید مطابقت دهید:

mv server.jar minecraft_server_1.18.1.jar

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

مرحله 3 – پیکربندی و اجرای سرور Minecraft

اکنون که jar Minecraft را دانلود کرده اید، آماده اجرای آن هستید.

ابتدا یک جلسه صفحه نمایش را با اجرای دستور screen شروع کنید:

screen

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

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

java -Xms1024M -Xmx1024M -jar minecraft_server_1.18.1.jar nogui

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

  • Xms1024M – این سرور را به گونه ای پیکربندی می کند که با 1024 مگابایت یا 1 گیگابایت رم در حال اجرا باشد. اگر می خواهید سرور شما با رم بیشتری شروع به کار کند، می توانید این محدودیت را افزایش دهید. هر دو M برای مگابایت و G برای گیگابایت گزینه های پشتیبانی می شوند. به عنوان مثال: Xms2G سرور را با 2 گیگابایت رم راه اندازی می کند.
  • Xmx1024M – این سرور را برای استفاده حداکثر از 1024M رم پیکربندی می کند. اگر می‌خواهید سرورتان در اندازه بزرگ‌تری اجرا شود، بازیکنان بیشتری را مجاز کنید، یا اگر احساس می‌کنید که سرورتان کند کار می‌کند، می‌توانید این محدودیت را افزایش دهید. برنامه های جاوا از این جهت منحصر به فرد هستند که همیشه از شما می خواهند حداکثر مقدار حافظه ای که می توانند استفاده کنند را مشخص کنید.
  • jar – این پرچم مشخص می کند که کدام فایل jar سرور اجرا شود.
  • nogui – این به سرور می گوید که رابط کاربری گرافیکی را راه اندازی نکند زیرا این یک سرور است و شما یک رابط کاربری گرافیکی ندارید.

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

 

Output

[22:05:31] [22:05:31] [main/ERROR]: Failed to load properties from file: server.properties
[22:05:31] [main/WARN]: Failed to load eula.txt
[22:05:31] [main/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

این خطاها به این دلیل ایجاد شده‌اند که سرور نمی‌تواند دو فایل لازم برای اجرا را پیدا کند: EULA (توافقنامه مجوز کاربر نهایی) که در eula.txt یافت می‌شود و فایل پیکربندی server.properties. از آنجایی که سرور قادر به یافتن این فایل ها نبود، آنها را در فهرست کاری فعلی شما ایجاد کرد. Minecraft این کار را عمدا انجام می دهد تا مطمئن شود که EULA آن را خوانده اید و با آن موافقت کرده اید.

eula.txt را در nano یا ویرایشگر متن مورد علاقه خود باز کنید:

nano eula.txt

در داخل این فایل، پیوندی به EULA Minecraft مشاهده خواهید کرد. URL را کپی کنید:

~/eula.txt

#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
#Tue Mar 24 22:05:31 UTC 2020
eula=false

URL را در مرورگر وب خود باز کنید و توافق نامه را بخوانید. سپس به ویرایشگر متن خود برگردید و آخرین خط را در eula.txt پیدا کنید. در اینجا eula=false را به eula=true تغییر دهید. سپس فایل را ذخیره کرده و ببندید. در نانو، این به این معنی است که Ctrl+X را برای خروج فشار دهید، سپس وقتی از شما خواسته شد ذخیره کنید، Y و سپس Enter کنید.

اکنون که EULA را پذیرفته اید، می توانید سرور را مطابق با مشخصات خود پیکربندی کنید.

در دایرکتوری فعلی خود، فایل server.properties ایجاد شده جدید را نیز خواهید یافت. این فایل شامل تمامی گزینه های پیکربندی سرور Minecraft شما می باشد. می‌توانید فهرست دقیقی از تمام ویژگی‌های سرور را در ویکی رسمی Minecraft پیدا کنید. قبل از راه اندازی سرور باید این فایل را با تنظیمات دلخواه خود تغییر دهید. این آموزش برخی از تنظیمات اساسی را پوشش می دهد:

nano server.properties

فایل شما به شکل زیر ظاهر می شود:

~/server.properties

#Minecraft server properties
#Thu Apr 30 23:42:29 UTC 2020
spawn-protection=16
max-tick-time=60000
query.port=25565
generator-settings=
force-gamemode=false
allow-nether=true
enforce-whitelist=false
gamemode=survival
broadcast-console-to-ops=true
enable-query=false
player-idle-timeout=0
difficulty=easy
spawn-monsters=true
broadcast-rcon-to-ops=true
op-permission-level=4
pvp=true
snooper-enabled=true
level-type=default
hardcore=false
enable-command-block=false
max-players=20
network-compression-threshold=256
resource-pack-sha1=
max-world-size=29999984
function-permission-level=2
rcon.port=25575
server-port=25565
server-ip=
spawn-npcs=true
allow-flight=false
level-name=world
view-distance=10
resource-pack=
spawn-animals=true
white-list=false
rcon.password=
generate-structures=true
online-mode=true
max-build-height=256
level-seed=
prevent-proxy-connections=false
use-native-transport=true
motd=A Minecraft Server
enable-rcon=false

بیایید نگاهی دقیق تر به برخی از مهم ترین ویژگی های این لیست بیندازیم:

دشواری (پیش‌فرض آسان) – این میزان سختی بازی را تعیین می‌کند، مانند میزان آسیب وارد شده و چگونگی تأثیر عناصر بر بازیکن شما. گزینه ها صلح آمیز، آسان، عادی و سخت هستند.
حالت بازی (بقای پیش فرض) – این حالت گیم پلی را تنظیم می کند. گزینه ها بقا، خلاقیت، ماجراجویی و تماشاگر هستند.
level-name (دنیای پیش فرض) – این نام سرور شما را تعیین می کند که در مشتری ظاهر می شود. ممکن است لازم باشد قبل از کاراکترهای خاص مانند آپوستروف، علامت معکوس وجود داشته باشد. شناخته شده است که این کاراکترهای فرار است، و زمانی که کاراکترهای خاص ممکن است به درستی در زمینه تجزیه و تحلیل نشوند، معمول است.
motd (سرور پیش فرض یک Minecraft) – پیامی که در لیست سرور مشتری Minecraft نمایش داده می شود.
pvp (پیش‌فرض درست) – نبرد بازیکن در مقابل بازیکن را فعال می‌کند. اگر روی true تنظیم شود، بازیکنان می‌توانند وارد جنگ شوند و به یکدیگر آسیب برسانند.
پس از تنظیم گزینه های مورد نظر، فایل را ذخیره کرده و ببندید.

اکنون می توانید سرور خود را با موفقیت راه اندازی کنید.

مانند دفعه قبل، بیایید سرور خود را با 1024M RAM راه اندازی کنیم. این بار، همچنین باید به Minecraft این امکان را بدهید که در صورت لزوم تا 4G از رم استفاده کند. به یاد داشته باشید که می توانید این شماره را متناسب با محدودیت های سرور یا نیازهای کاربر خود تنظیم کنید:

java -Xms1024M -Xmx4G -jar minecraft_server_1.18.1.jar nogui

چند لحظه به مقدار دهی اولیه بدهید. به زودی سرور Minecraft جدید شما شروع به تولید خروجی مشابه این خواهد کرد:

 

Output

[21:08:14] [Server thread/INFO]: Starting minecraft server version 1.15.2
[21:08:14] [Server thread/INFO]: Loading properties
[21:08:14] [Server thread/INFO]: Default game type: SURVIVAL
[21:08:14] [Server thread/INFO]: Generating keypair
[21:08:15] [Server thread/INFO]: Starting minecraft server on *:25565

پس از راه اندازی سرور، خروجی زیر را مشاهده خواهید کرد:

 

Output

[21:15:37] [Server thread/INFO]: Done (30.762s)! For help, type "help"

سرور شما اکنون در حال اجرا است و کنترل پنل مدیر سرور به شما نمایش داده شده است. راهنمای تایپ کردن را امتحان کنید:

help

خروجی به شکل زیر ظاهر می شود:

 

Output

[21:15:37] [Server thread/INFO]: /advancement (grant|revoke)
[21:15:37] [Server thread/INFO]: /ban <targets> [<reason>]
[21:15:37] [Server thread/INFO]: /ban-ip <target> [<reason>]
[21:15:37] [Server thread/INFO]: /banlist [ips|players]
...

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

مرحله 4 – نگه داشتن سرور در حال اجرا

اکنون که سرور خود را روشن کرده اید، می خواهید حتی پس از قطع اتصال از جلسه SSH، همچنان در حال اجرا باشد. از آنجایی که قبلاً از صفحه استفاده کرده اید، می توانید با فشار دادن Ctrl + A + D از این جلسه جدا شوید. باید ببینید که به پوسته اصلی خود برگشته اید:

 

Output

​​ubuntu@minecraft-1804:~$ screen
[detached from 3626.pts-0.minecraft-1804]
$

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

screen -list

یک خروجی با شناسه جلسه خود دریافت خواهید کرد که برای از سرگیری آن جلسه باید آن را از سر بگیرید:

 

Output

There is a screen on:
        3626.pts-0.minecraft-1804 (11/16/21 22:56:33) (Detached)
1 Socket in /run/screen/S-root.

برای از سرگیری جلسه خود، پرچم -r را به فرمان صفحه ارسال کنید و سپس شناسه جلسه خود را وارد کنید:

screen -r 3626

وقتی دوباره آماده خروج از ترمینال شدید، حتما با Ctrl + A + D از جلسه جدا شده و سپس از سیستم خارج شوید.

مرحله 5 – اتصال به سرور خود از مشتری Minecraft

اکنون که سرور شما راه اندازی شده است، بیایید از طریق مشتری Minecraft به آن متصل شویم. سپس می توانید بازی کنید!

نسخه Minecraft Java Edition خود را اجرا کنید و Multiplayer را در منو انتخاب کنید.

در مرحله بعد، باید یک سرور برای اتصال به آن اضافه کنید، بنابراین روی دکمه افزودن سرور کلیک کنید.

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

هنگامی که نام سرور و آدرس IP خود را وارد کردید، به صفحه Multiplayer بازگردانده می شوید، جایی که سرور شما اکنون لیست می شود.

از این پس سرور شما همیشه در این لیست ظاهر می شود. آن را انتخاب کرده و روی Join Server کلیک کنید.

شما در سرور خود هستید و آماده بازی هستید!

نتیجه

شما اکنون یک سرور Minecraft دارید که روی اوبونتو 18.04 اجرا می شود تا شما و همه دوستانتان با آن بازی کنید! از کاوش، کاردستی و زنده ماندن در یک دنیای خام سه بعدی لذت ببرید.

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

برچسب‌ها:Minecraft نصباتصال به سرور مجازیاوبونتو 18.04ایجاد یک سرور Minecraftخرید سرور مجازیسرور Minecraftسرور مجازیسرور مجازی آمریکاسرور مجازی لهستان

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه انجام جستجوی تمام متن در MongoDB

ورود به سایت

معرفی

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

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

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

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

پیش نیازها

برای دنبال کردن این آموزش، شما نیاز دارید:

  • سروری با کاربر معمولی و غیر روت با امتیازات sudo و فایروال پیکربندی شده با UFW. این آموزش با استفاده از سروری که اوبونتو 20.04 را اجرا می کند تأیید شده است، و شما می توانید با دنبال کردن این آموزش اولیه راه اندازی سرور برای اوبونتو 20.04 سرور خود را آماده کنید.
  • MongoDB روی سرور شما نصب شده است.
  • نمونه MongoDB سرور شما با فعال کردن احراز هویت و ایجاد یک کاربر مدیریتی ایمن می شود
  • آشنایی با پرس و جو مجموعه های MongoDB و فیلتر کردن نتایج.

مرحله 1 – آماده سازی داده های تست

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

برای ایجاد این مجموعه نمونه، به عنوان کاربر مدیریتی خود به پوسته MongoDB متصل شوید. این آموزش از قراردادهای آموزش امنیتی MongoDB پیش نیاز پیروی می کند و فرض می کند که نام این کاربر مدیریتی AdminSammy و پایگاه داده احراز هویت آن admin است. مطمئن شوید که این جزئیات را در دستور زیر تغییر دهید تا تنظیمات خود را نشان دهد، اگر متفاوت است:

mongo -u AdminSammy -p –authenticationDatabase admin

رمز عبوری را که در حین نصب تنظیم کرده اید وارد کنید تا به پوسته دسترسی پیدا کنید. پس از ارائه رمز عبور، درخواست شما به علامت بزرگتر از تغییر خواهد کرد:

>

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

Example Cafecito document

{
    "name": "Cafecito",
    "description": "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam."
}

این سند شامل دو فیلد است: نام نوشیدنی قهوه و توضیحات طولانی تر که اطلاعات پس زمینه ای در مورد نوشیدنی و مواد تشکیل دهنده آن ارائه می دهد.

متد insertMany() زیر را در پوسته MongoDB اجرا کنید تا مجموعه‌ای به نام recipes ایجاد کنید و در همان زمان، پنج سند نمونه را در آن قرار دهید:

db.recipes.insertMany([
{“name”: “Cafecito”, “description”: “A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam.”},
{“name”: “New Orleans Coffee”, “description”: “Cafe Noir from New Orleans is a spiced, nutty coffee made with chicory.”},
{“name”: “Affogato”, “description”: “An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream.”},
{“name”: “Maple Latte”, “description”: “A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup.”},
{“name”: “Pumpkin Spice Latte”, “description”: “It wouldn’t be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree.”}
])

 

این متد لیستی از شناسه‌های شی اختصاص داده شده به اشیاء تازه درج شده را برمی‌گرداند:

 

Output

{
        "acknowledged" : true,
        "insertedIds" : [
            ObjectId("61895d2787f246b334ece911"),
            ObjectId("61895d2787f246b334ece912"),
            ObjectId("61895d2787f246b334ece913"),
            ObjectId("61895d2787f246b334ece914"),
            ObjectId("61895d2787f246b334ece915")
        ]
}

می توانید با اجرای متد find() در مجموعه دستور العمل ها بدون آرگومان بررسی کنید که اسناد به درستی درج شده اند. با این کار تمام اسناد موجود در مجموعه بازیابی می شود:

db.recipes.find()

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }
. . .

با داده های نمونه در محل، آماده شروع یادگیری نحوه استفاده از ویژگی های جستجوی متن کامل MongoDB هستید.

مرحله 2 – ایجاد یک فهرست متن

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

با این حال، نمایه متنی، نوع خاصی از نمایه است که برای تسهیل بیشتر جستجوی فیلدهای حاوی داده های متنی استفاده می شود. هنگامی که کاربر یک فهرست متنی ایجاد می کند، MongoDB به طور خودکار هر کلمه توقف خاص زبان را از جستجو حذف می کند. این بدان معنی است که MongoDB رایج ترین کلمات برای زبان داده شده (در انگلیسی، کلماتی مانند “a”، “an”، “the” یا “this”) را نادیده می گیرد.

MongoDB همچنین نوعی پسوند stemming را در جستجوها پیاده سازی خواهد کرد. این شامل شناسایی قسمت ریشه عبارت جستجو شده توسط MongoDB و استفاده از سایر اشکال دستور زبان آن ریشه (که با افزودن پسوندهای رایج مانند “-ing”، “-ed” یا شاید “-er” ایجاد شده است) را به عنوان معادل ریشه برای کلمه جستجو می کند.

به لطف این ویژگی‌ها و سایر ویژگی‌ها، MongoDB می‌تواند با انعطاف‌پذیری بیشتری از پرسش‌های نوشته شده به زبان طبیعی پشتیبانی کند و نتایج بهتری ارائه دهد.

شما فقط می توانید یک فهرست متنی برای هر مجموعه MongoDB ایجاد کنید، اما این فهرست را می توان با استفاده از بیش از یک فیلد ایجاد کرد. در مجموعه مثال ما، متن مفیدی در هر دو قسمت نام و توضیحات هر سند ذخیره شده است. ایجاد یک فهرست متنی برای هر دو فیلد می تواند مفید باشد.

متد ()createIndex زیر را اجرا کنید که یک فهرست متنی برای دو فیلد ایجاد می کند:

db.recipes.createIndex({ “name”: “text”, “description”: “text” });

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

 

Output

{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

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

مرحله 3 – جستجو برای یک یا چند کلمه جداگانه

شاید رایج ترین مشکل جستجو جستجوی اسنادی باشد که حاوی یک یا چند کلمه جداگانه هستند.

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

همچنین این روشی است که MongoDB هنگام استفاده از نمایه های متنی به پرس و جوهای جستجوی معمولی نزدیک می شود. در این مرحله توضیح داده می شود که MongoDB چگونه پرس و جوهای جستجو را با چند مثال تفسیر می کند.

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

db.recipes.find({ $text: { $search: “spiced” } });

توجه داشته باشید که نحو هنگام استفاده از جستجوی تمام متن کمی با پرس و جوهای معمولی متفاوت است. نام فیلدهای فردی – مانند نام یا توضیحات – در سند فیلتر ظاهر نمی شوند. در عوض، کوئری از عملگر $text استفاده می‌کند و به MongoDB می‌گوید که این کوئری قصد دارد از فهرست متنی که قبلا ایجاد کرده‌اید استفاده کند. لازم نیست بیشتر از آن مشخص باشید، زیرا همانطور که به یاد دارید، یک مجموعه ممکن است فقط یک فهرست متنی داشته باشد. در داخل سند جاسازی شده برای این فیلتر، اپراتور $search است که عبارت جستجو را به عنوان مقدار آن در نظر گرفته است. در این مثال، پرس و جو یک کلمه است: spiced.

پس از اجرای این دستور، MongoDB لیستی از اسناد زیر را تولید می کند:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece915"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree." }
{ "_id" : ObjectId("61895d2787f246b334ece912"), "name" : "New Orleans Coffee", "description" : "Cafe Noir from New Orleans is a spiced, nutty coffee made with chicory." }

دو سند در مجموعه نتایج وجود دارد که هر دو حاوی کلماتی شبیه عبارت جستجو هستند. در حالی که سند قهوه نیواورلئان دارای کلمه تند در توضیحات است، سند Pumpkin Spice Late چنین نیست.

صرف نظر از این، به لطف استفاده MongoDB از stemming، همچنان با این کوئری بازگردانده شد. MongoDB کلمه spiced را به صرف ادویه حذف کرد، ادویه را در فهرست جستجو کرد و همچنین آن را ریشه‌یابی کرد. به همین دلیل، کلمات ادویه و ادویه در سند Pumpkin Spice Late با عبارت جستجو با موفقیت مطابقت داشت، حتی اگر هیچ یک از آن کلمات را به طور خاص جستجو نکردید.

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

db.recipes.find({ $text: { $search: “spiced espresso” } });

لیست نتایج این بار طولانی تر از قبل است:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece914"), "name" : "Maple Latte", "description" : "A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup." }
{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream." }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }
{ "_id" : ObjectId("61895d2787f246b334ece915"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree." }
{ "_id" : ObjectId("61895d2787f246b334ece912"), "name" : "New Orleans Coffee", "description" : "Cafe Noir from New Orleans is a spiced, nutty coffee made with chicory." }

هنگام استفاده از چندین کلمه در یک عبارت جستجو، MongoDB یک عملیات OR منطقی را انجام می دهد، بنابراین یک سند فقط باید با یک قسمت از عبارت مطابقت داشته باشد تا در مجموعه نتایج گنجانده شود. نتایج حاوی اسنادی است که هم دارای ادویه و هم اسپرسو یا هر یک از آنها به تنهایی است. توجه داشته باشید که تا زمانی که کلمات در جایی در سند ظاهر می شوند، لزوماً نیازی نیست که در نزدیکی یکدیگر ظاهر شوند.

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

مرحله 4 – جستجوی عبارات کامل و استفاده از موارد استثنا

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

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

db.recipes.find({ $text: { $search: “ice cream” } });

پایگاه داده دو دستور پخت قهوه را برمی گرداند:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream." }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }

در حالی که سند Affogato با انتظارات شما مطابقت دارد، Cafecito با بستنی درست نمی شود. موتور جستجو با استفاده از عملیات منطقی OR، نتیجه دوم را فقط به این دلیل پذیرفت که کلمه کرم در توضیحات آمده است.

برای اینکه به MongoDB بگویید که به دنبال بستنی به عنوان یک عبارت کامل هستید و نه دو کلمه جداگانه، از عبارت زیر استفاده کنید:

db.recipes.find({ $text: { $search: “\”ice cream\”” } });

به علامت‌های معکوس قبل از هر یک از نقل‌قول‌های دوگانه اطراف عبارت: \”ice cream\” توجه کنید. عبارت جستجویی که اجرا می‌کنید «ice cream» است، با دو نقل قول نشان‌دهنده عبارتی است که باید دقیقاً مطابقت داشته باشد. اسلش‌های معکوس (\) از گیومه‌های دوتایی فرار می‌کنند، بنابراین به عنوان بخشی از نحو JSON در نظر گرفته نمی‌شوند، زیرا می‌توانند در مقدار عملگر $search ظاهر شوند.

این بار، MongoDB یک نتیجه را برمی گرداند:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream." }

این سند دقیقاً با عبارت جستجو مطابقت دارد و نه خامه و نه یخ به تنهایی برای به حساب آوردن یک مسابقه کافی نیست.

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

db.recipes.find({ $text: { $search: “espresso” } });

این پرس و جو چهار سند را برمی گرداند:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece914"), "name" : "Maple Latte", "description" : "A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup." }
{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream." }
{ "_id" : ObjectId("61895d2787f246b334ece915"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree." }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }

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

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

db.recipes.find({ $text: { $search: “espresso -milk” } });

با این پرس و جو، دو سند از نتایج برگشت داده شده قبلی حذف می شوند:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream." }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }

شما همچنین می توانید عبارات کامل را حذف کنید. برای جستجوی قهوه های بدون بستنی، می توانید -“ice cream” را در عبارت جستجوی خود قرار دهید. باز هم، باید از نقل قول های دوگانه با اسلش های معکوس فرار کنید، مانند این:

db.recipes.find({ $text: { $search: “espresso -\”ice cream\”” } });

 

Output

{ "_id" : ObjectId("61d48c31a285f8250c8dd5e6"), "name" : "Maple Latte", "description" : "A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup." }
{ "_id" : ObjectId("61d48c31a285f8250c8dd5e7"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree." }
{ "_id" : ObjectId("61d48c31a285f8250c8dd5e3"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam." }

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

مرحله 5 – امتیاز دادن به نتایج و مرتب سازی بر اساس امتیاز

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

موتورهای جستجوی متن کامل معمولاً یک امتیاز مربوط به نتایج جستجو را تعیین می‌کنند که نشان می‌دهد تا چه حد با عبارت جستجو مطابقت دارند. MongoDB نیز این کار را انجام می دهد، اما ارتباط جستجو به طور پیش فرض قابل مشاهده نیست.

یک بار دیگر اسپرسوی تند را جستجو کنید، اما این بار MongoDB امتیاز مربوط به جستجوی هر نتیجه را نیز بازگردانید. برای انجام این کار، می توانید پس از سند فیلتر پرس و جو یک طرح اضافه کنید:

db.recipes.find(
{ $text: { $search: “spiced espresso” } },
{ score: { $meta: “textScore” } }
)

طرح ریزی { score: {$meta: “textScore” } } از عملگر $meta استفاده می کند، نوع خاصی از طرح ریزی که ابرداده خاصی را از اسناد برگشتی برمی گرداند. این مثال ابرداده textScore اسناد را برمی‌گرداند، یکی از ویژگی‌های داخلی موتور جستجوی متن کامل MongoDB که حاوی امتیاز مربوط به جستجو است.

پس از اجرای پرس و جو، اسناد برگشتی شامل یک فیلد جدید به نام score می شود، همانطور که در سند فیلتر مشخص شده است:

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream.", "score" : 0.5454545454545454 }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam.", "score" : 0.5384615384615384 }
{ "_id" : ObjectId("61895d2787f246b334ece914"), "name" : "Maple Latte", "description" : "A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup.", "score" : 0.55 }
{ "_id" : ObjectId("61895d2787f246b334ece912"), "name" : "New Orleans Coffee", "description" : "Cafe Noir from New Orleans is a spiced, nutty coffee made with chicory.", "score" : 0.5454545454545454 }
{ "_id" : ObjectId("61895d2787f246b334ece915"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree.", "score" : 2.0705128205128203 }

توجه کنید که امتیاز Pumpkin Spice Latte چقدر بالاتر است، تنها نوشیدنی قهوه که حاوی کلمات spiced و اسپرسو است. با توجه به امتیاز مرتبط MongoDB، مرتبط ترین سند برای آن پرس و جو است. با این حال، به طور پیش فرض، نتایج به ترتیب مرتبط بودن برگردانده نمی شوند.

برای تغییر آن، می توانید یک بند sort() به پرس و جو اضافه کنید، مانند این:

db.recipes.find(
{ $text: { $search: “spiced espresso” } },
{ score: { $meta: “textScore” } }
).sort(
{ score: { $meta: “textScore” } }
);

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

 

Output

{ "_id" : ObjectId("61895d2787f246b334ece915"), "name" : "Pumpkin Spice Latte", "description" : "It wouldn't be autumn without pumpkin spice lattes made with espresso, steamed milk, cinnamon spices, and pumpkin puree.", "score" : 2.0705128205128203 }
{ "_id" : ObjectId("61895d2787f246b334ece914"), "name" : "Maple Latte", "description" : "A wintertime classic made with espresso and steamed milk and sweetened with some maple syrup.", "score" : 0.55 }
{ "_id" : ObjectId("61895d2787f246b334ece913"), "name" : "Affogato", "description" : "An Italian sweet dessert coffee made with fresh-brewed espresso and vanilla ice cream.", "score" : 0.5454545454545454 }
{ "_id" : ObjectId("61895d2787f246b334ece912"), "name" : "New Orleans Coffee", "description" : "Cafe Noir from New Orleans is a spiced, nutty coffee made with chicory.", "score" : 0.5454545454545454 }
{ "_id" : ObjectId("61895d2787f246b334ece911"), "name" : "Cafecito", "description" : "A sweet and rich Cuban hot coffee made by topping an espresso shot with a thick sugar cream foam.", "score" : 0.5384615384615384 }

سند Pumpkin Spice Latte به عنوان اولین نتیجه ظاهر می شود زیرا دارای بالاترین امتیاز مرتبط است.

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

نتیجه

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

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

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از Ansible Vault برای محافظت از داده های حساس Playbook

ورود به سایت

معرفی

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

در این راهنما، نحوه استفاده از Ansible Vault را نشان خواهیم داد و برخی از روش‌های توصیه شده برای ساده‌سازی استفاده از آن را بررسی خواهیم کرد. ما از سرور اوبونتو 20.04 برای ماشین کنترلی Ansible استفاده خواهیم کرد. به هاست راه دور نیاز نیست.

پیش نیازها

برای پیگیری، به یک سرور اوبونتو 20.04 با یک کاربر غیر ریشه با امتیازات sudo نیاز دارید. شما می توانید راهنمای راه اندازی سرور اولیه Ubuntu 20.04 ما را دنبال کنید تا کاربری با مجوزهای مناسب ایجاد کنید.

در سرور، باید Ansible را نصب و پیکربندی کنید. برای نصب بسته های مناسب می توانید آموزش نصب Ansible در اوبونتو 20.04 را دنبال کنید.

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

Ansible Vault چیست؟

Ansible Vault مکانیزمی است که به محتوای رمزگذاری شده اجازه می دهد تا به طور شفاف در جریان های کاری Ansible گنجانده شود. ابزاری به نام ansible-vault داده‌های محرمانه به نام Secrets را با رمزگذاری روی دیسک ایمن می‌کند. برای ادغام این اسرار با داده‌های معمولی Ansible، هر دو دستور ansible و ansible-playbook، به ترتیب برای اجرای وظایف موقت و playbook ساختاریافته، از رمزگشایی محتوای رمزگذاری‌شده در طاق در زمان اجرا پشتیبانی می‌کنند.

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

اکنون که کمی در مورد Vault چیست، می‌توانیم درباره ابزارهایی که Ansible ارائه می‌کند و نحوه استفاده از Vault با گردش‌های کاری موجود بحث کنیم.

تنظیم ویرایشگر Ansible Vault

قبل از استفاده از دستور ansible-vault، ایده خوبی است که ویرایشگر متن مورد نظر خود را مشخص کنید. تعدادی از دستورات Vault شامل باز کردن یک ویرایشگر برای دستکاری محتوای یک فایل رمزگذاری شده است. Ansible به متغیر محیط EDITOR نگاه می کند تا ویرایشگر مورد نظر شما را پیدا کند. اگر این تنظیم نشده باشد، به طور پیش فرض روی vi خواهد بود.

اگر نمی خواهید با ویرایشگر vi ویرایش کنید، باید متغیر EDITOR را در محیط خود تنظیم کنید.

برای تنظیم ویرایشگر برای یک فرمان فردی، دستور را با انتساب متغیر محیطی به صورت زیر اضافه کنید:

EDITOR=nano ansible-vault . . .

برای تداوم این موضوع، فایل ~/.bashrc خود را باز کنید:

nano ~/.bashrc

ویرایشگر مورد نظر خود را با افزودن یک تخصیص EDITOR به انتهای فایل مشخص کنید:

~/.bashrc

export EDITOR=nano

پس از اتمام کار فایل را ذخیره کرده و ببندید.

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

. ~/.bashrc

برای بررسی اینکه تنظیمات شما اعمال شده است، متغیر EDITOR را نمایش دهید:

echo $EDITOR

 

Output

nano

اکنون که ویرایشگر دلخواه خود را ایجاد کرده اید، می توانیم عملیات های موجود را با دستور ansible-vault مورد بحث قرار دهیم.

نحوه مدیریت فایل های حساس با ansible-vault

دستور ansible-vault رابط اصلی برای مدیریت محتوای رمزگذاری شده در Ansible است. این دستور در ابتدا برای رمزگذاری فایل ها استفاده می شود و سپس برای مشاهده، ویرایش یا رمزگشایی داده ها استفاده می شود.

ایجاد فایل های رمزگذاری شده جدید

برای ایجاد یک فایل جدید رمزگذاری شده با Vault، از دستور ansible-vault create استفاده کنید. نام فایلی را که می خواهید ایجاد کنید ارسال کنید. به عنوان مثال، برای ایجاد یک فایل YAML رمزگذاری شده به نام vault.yml برای ذخیره متغیرهای حساس، می توانید تایپ کنید:

ansible-vault create vault.yml

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

 

Output

New Vault password: 
Confirm New Vault password:

هنگامی که رمز عبور خود را تأیید کردید، Ansible بلافاصله یک پنجره ویرایش باز می کند که در آن می توانید مطالب مورد نظر خود را وارد کنید.

برای آزمایش عملکرد رمزگذاری، متن آزمایشی را وارد کنید:

vault.yml

Secret information

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

cat vault.yml

 

Output

$ANSIBLE_VAULT;1.1;AES256
65316332393532313030636134643235316439336133363531303838376235376635373430336333
3963353630373161356638376361646338353763363434360a363138376163666265336433633664
30336233323664306434626363643731626536643833336638356661396364313666366231616261
3764656365313263620a383666383233626665376364323062393462373266663066366536306163
31643731343666353761633563633634326139396230313734333034653238303166

ما می‌توانیم برخی از اطلاعات هدر را ببینیم که Ansible برای اطلاع از نحوه مدیریت فایل استفاده می‌کند و به دنبال آن محتویات رمزگذاری‌شده که به صورت اعداد نمایش داده می‌شوند.

رمزگذاری فایل های موجود

اگر از قبل فایلی دارید که می خواهید با Vault رمزگذاری کنید، به جای آن از دستور encrypt ansible-vault استفاده کنید.

برای آزمایش، می‌توانیم با تایپ کردن یک فایل نمونه ایجاد کنیم:

echo ‘unencrypted stuff’ > encrypt_me.txt

اکنون می توانید فایل موجود را با تایپ کردن رمزگذاری کنید:

ansible-vault encrypt encrypt_me.txt

مجدداً از شما خواسته می شود رمز عبور را ارائه و تأیید کنید. پس از آن، یک پیام رمزگذاری را تایید می کند:

 

Output

New Vault password: 
Confirm New Vault password:
Encryption successful

به جای باز کردن یک پنجره ویرایش، ansible-vault محتویات فایل را رمزگذاری می کند و آن را روی دیسک می نویسد و نسخه رمزگذاری نشده را جایگزین می کند.

اگر فایل را بررسی کنیم، باید یک الگوی رمزگذاری شده مشابه را ببینیم:

cat encrypt_me.txt

 

Output

$ANSIBLE_VAULT;1.1;AES256
66633936653834616130346436353865303665396430383430353366616263323161393639393136
3737316539353434666438373035653132383434303338640a396635313062386464306132313834
34313336313338623537333332356231386438666565616537616538653465333431306638643961
3636663633363562320a613661313966376361396336383864656632376134353039663662666437
39393639343966363565636161316339643033393132626639303332373339376664

همانطور که می بینید، Ansible محتوای موجود را به همان روشی که فایل های جدید را رمزگذاری می کند، رمزگذاری می کند.

مشاهده فایل های رمزگذاری شده

گاهی اوقات، ممکن است لازم باشد به محتویات یک فایل رمزگذاری شده بدون نیاز به ویرایش یا نوشتن آن در سیستم فایل بدون رمزگذاری، ارجاع دهید. دستور ansible-vault view محتویات یک فایل را به صورت استاندارد تغذیه می کند. به طور پیش فرض، این بدان معنی است که محتویات در ترمینال نمایش داده می شوند.

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

ansible-vault view vault.yml

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

 

Output

Vault password:
Secret information

همانطور که می بینید، درخواست رمز عبور در خروجی محتویات فایل مخلوط می شود. هنگام استفاده از نمای ansible-vault در فرآیندهای خودکار این را در نظر داشته باشید.

ویرایش فایل های رمزگذاری شده

هنگامی که نیاز به ویرایش یک فایل رمزگذاری شده دارید، از دستور ansible-vault edit استفاده کنید:

ansible-vault edit vault.yml

 

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

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

رمزگشایی دستی فایل های رمزگذاری شده

برای رمزگشایی یک فایل رمزگذاری شده vault، از دستور ansible-vault decrypt استفاده کنید.

نام فایل رمزگذاری شده را ارسال کنید:

ansible-vault decrypt vault.yml

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

 

Output

Vault password:
Secret information

همانطور که می بینید، درخواست رمز عبور در خروجی محتویات فایل مخلوط می شود. هنگام استفاده از نمای ansible-vault در فرآیندهای خودکار این را در نظر داشته باشید.

ویرایش فایل های رمزگذاری شده

هنگامی که نیاز به ویرایش یک فایل رمزگذاری شده دارید، از دستور ansible-vault edit استفاده کنید:

ansible-vault edit vault.yml

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

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

رمزگشایی دستی فایل های رمزگذاری شده

برای رمزگشایی یک فایل رمزگذاری شده vault، از دستور ansible-vault decrypt استفاده کنید.

نام فایل رمزگذاری شده را ارسال کنید:

ansible-vault decrypt vault.yml

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

 

Output

Vault password:
Decryption successful

اگر دوباره فایل را مشاهده کنید، به جای رمزگذاری طاق، باید محتوای واقعی فایل را ببینید:

cat vault.yml

 

Output

Secret information

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

تغییر رمز عبور فایل های رمزگذاری شده

اگر نیاز به تغییر رمز عبور یک فایل رمزگذاری شده دارید، از دستور ansible-vault rekey استفاده کنید:

ansible-vault rekey encrypt_me.txt

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

 

Output

Vault password:

پس از وارد کردن آن، از شما خواسته می شود رمز عبور جدید صندوق را انتخاب و تأیید کنید:

 

Output

Vault password:
New Vault password:
Confirm New Vault password:

هنگامی که رمز عبور جدید را با موفقیت تأیید کردید، پیامی مبنی بر موفقیت در فرآیند رمزگذاری مجدد دریافت خواهید کرد:

 

Output

Rekey successful

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

اجرای Ansible با فایل‌های رمزگذاری‌شده Vault

پس از اینکه اطلاعات حساس خود را با Vault رمزگذاری کردید، می توانید از فایل ها با ابزار معمولی Ansible استفاده کنید. دستورهای ansible و ansible-playbook هر دو می‌دانند چگونه فایل‌های محافظت‌شده در صندوق را با در نظر گرفتن رمز عبور صحیح رمزگشایی کنند. بسته به نیاز شما چند راه مختلف برای ارائه رمز عبور برای این دستورات وجود دارد.

برای پیگیری، به یک فایل رمزگذاری شده در طاق نیاز دارید. با تایپ کردن می توانید یکی ایجاد کنید:

ansible-vault create secret_key

رمز عبور را انتخاب و تأیید کنید. هر محتوای ساختگی را که می خواهید پر کنید:

secret_key

confidential data

ذخیره کنید و فایل را ببندید.

همچنین می توانیم یک فایل میزبان موقت به عنوان موجودی ایجاد کنیم:

nano hosts

ما فقط لوکال هاست Ansible را به آن اضافه می کنیم. برای آماده شدن برای مرحله بعدی، آن را در گروه [پایگاه داده] قرار می دهیم:

hosts

[database]
localhost ansible_connection=local

پس از اتمام کار فایل را ذخیره کرده و ببندید.

در مرحله بعد، یک فایل ansible.cfg در دایرکتوری فعلی ایجاد کنید، اگر قبلاً وجود نداشته باشد:

nano ansible.cfg

در حال حاضر، فقط یک بخش [پیش‌فرض] اضافه کنید و Ansible را به موجودی که ایجاد کردیم اضافه کنید:

ansible.cfg

[defaults]
inventory = ./hosts

وقتی آماده شدید، ادامه دهید.

استفاده از یک اعلان تعاملی

ساده ترین راه برای رمزگشایی محتوا در زمان اجرا این است که Ansible اعتبار مناسب را از شما بخواهد. می توانید این کار را با افزودن –ask-vault-pass به هر دستور ansible یا ansible-playbook انجام دهید. Ansible از شما رمز عبوری می خواهد که از آن برای رمزگشایی هر محتوای محافظت شده در خزانه که پیدا می کند استفاده می کند.

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

ansible –ask-vault-pass -bK -m copy -a ‘src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root’ localhost

وظیفه ما مشخص می کند که مالکیت فایل باید به روت تغییر کند، بنابراین امتیازات مدیریتی مورد نیاز است. پرچم -bK به Ansible می گوید که رمز عبور sudo را برای میزبان مورد نظر درخواست کند، بنابراین از شما رمز عبور sudo خواسته می شود. سپس از شما رمز عبور Vault خواسته می شود:

 

Output

BECOME password:
Vault password:

هنگامی که رمز عبور ارائه می شود، Ansible تلاش می کند تا با استفاده از رمز عبور Vault برای هر فایل رمزگذاری شده ای که پیدا می کند، کار را اجرا کند. به خاطر داشته باشید که تمام فایل هایی که در حین اجرا به آنها ارجاع داده می شود باید از یک رمز عبور استفاده کنند:

 

Output

localhost | SUCCESS => {
    "changed": true, 
    "checksum": "7a2eb5528c44877da9b0250710cba321bc6dac2d", 
    "dest": "/tmp/secret_key", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "270ac7da333dd1db7d5f7d8307bd6b41", 
    "mode": "0600", 
    "owner": "root", 
    "size": 18, 
    "src": "/home/sammy/.ansible/tmp/ansible-tmp-1480978964.81-196645606972905/source", 
    "state": "file", 
    "uid": 0
}

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

استفاده از Ansible Vault با یک فایل رمز عبور

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

به عنوان مثال، می توانید رمز عبور خود را در یک فایل .vault_pass مانند این قرار دهید:

echo ‘my_vault_password’ > .vault_pass

اگر از کنترل نسخه استفاده می کنید، مطمئن شوید که فایل رمز عبور را به فایل نادیده گرفتن نرم افزار کنترل نسخه خود اضافه کنید تا از انجام تصادفی آن جلوگیری کنید:

echo ‘.vault_pass’ >> .gitignore

اکنون می توانید به جای آن به فایل ارجاع دهید. پرچم –vault-password-file در خط فرمان موجود است. می‌توانیم همان کار را از قسمت آخر با تایپ کردن کامل کنیم:

ansible –vault-password-file=.vault_pass -bK -m copy -a ‘src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root’ localhost

این بار رمز عبور Vault از شما خواسته نمی شود.

خواندن خودکار فایل رمز عبور

برای جلوگیری از ارائه پرچم، می توانید متغیر محیطی ANSIBLE_VAULT_PASSWORD_FILE را با مسیر فایل رمز عبور تنظیم کنید:

export ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass

اکنون باید بتوانید دستور را بدون پرچم –vault-password-file برای جلسه جاری اجرا کنید:

ansible -bK -m copy -a ‘src=secret_key dest=/tmp/secret_key mode=0600 owner=root group=root’ localhost

برای آگاه کردن Ansible از محل فایل رمز عبور در جلسات، می توانید فایل ansible.cfg خود را ویرایش کنید.

فایل ansible.cfg محلی را که قبلا ایجاد کردیم باز کنید:

nano ansible.cfg

در بخش [defaults]، تنظیمات vault_password_file را تنظیم کنید. به محل فایل رمز عبور خود اشاره کنید. این می تواند یک مسیر نسبی یا مطلق باشد، بسته به اینکه کدام یک برای شما مفیدتر است:

ansible.cfg

[defaults]
. . .
vault_password_file = ./.vault_pass

اکنون، وقتی دستوراتی را اجرا می‌کنید که نیاز به رمزگشایی دارند، دیگر از شما خواسته نمی‌شود که پسورد vault را وارد کنید. به عنوان یک امتیاز، ansible-vault نه تنها از رمز عبور موجود در فایل برای رمزگشایی هر فایلی استفاده می کند، بلکه رمز عبور را هنگام ایجاد فایل های جدید با ایجاد ansible-vault و ensible-vault encrypt اعمال می کند.

خواندن رمز عبور از یک متغیر محیطی

ممکن است نگران ارسال تصادفی فایل رمز عبور خود به مخزن خود باشید. در حالی که Ansible یک متغیر محیطی برای اشاره به محل یک فایل رمز عبور دارد، اما متغیری برای تنظیم رمز عبور ندارد.

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

فایل .vault_pass خود را در ویرایشگر خود باز کنید:

nano .vault_pass

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

.vault_pass

#!/usr/bin/env python3

import os
print os.environ['VAULT_PASSWORD']

فایل را با تایپ کردن قابل اجرا کنید:

chmod +x .vault_pass

سپس می توانید متغیر محیطی VAULT_PASSWORD را تنظیم و صادر کنید، که برای جلسه فعلی شما در دسترس خواهد بود:

export VAULT_PASSWORD=my_vault_password

شما باید این کار را در ابتدای هر جلسه Ansible انجام دهید، که ممکن است ناخوشایند به نظر برسد. با این حال، این کار به طور موثری از انجام تصادفی رمز عبور رمزگذاری Vault شما محافظت می کند، که می تواند اشکالات جدی داشته باشد.

استفاده از متغیرهای رمزگذاری شده در Vault با متغیرهای منظم

در حالی که Ansible Vault را می توان با فایل های دلخواه استفاده کرد، اغلب برای محافظت از متغیرهای حساس استفاده می شود. ما از طریق یک مثال کار خواهیم کرد تا به شما نشان دهیم که چگونه یک فایل متغیرهای معمولی را به پیکربندی تبدیل کنید که امنیت و قابلیت استفاده را متعادل می کند.

تنظیم مثال

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

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

mkdir -p group_vars
nano group_vars/database

در داخل فایل group_vars/database، چند متغیر معمولی اضافه می کنیم. برخی از متغیرها، مانند شماره پورت MySQL، مخفی نیستند و می توانند آزادانه به اشتراک گذاشته شوند. سایر متغیرها، مانند رمز عبور پایگاه داده، محرمانه خواهند بود:

group_vars/database

---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

# sensitive data
mysql_password: supersecretpassword

می‌توانیم آزمایش کنیم که همه متغیرها با ماژول اشکال زدایی Ansible و متغیر hostvars در دسترس میزبان ما هستند:

ansible -m debug -a ‘var=hostvars[inventory_hostname]’ database

 

Output

localhost | SUCCESS => {
    "hostvars[inventory_hostname]": {
        "ansible_check_mode": false, 
        "ansible_version": {
            "full": "2.2.0.0", 
            "major": 2, 
            "minor": 2, 
            "revision": 0, 
            "string": "2.2.0.0"
        }, 
        "group_names": [
            "database"
        ], 
        "groups": {
            "all": [
                "localhost"
            ], 
            "database": [
                "localhost"
            ], 
            "ungrouped": []
        }, 
        "inventory_dir": "/home/sammy", 
        "inventory_file": "hosts", 
        "inventory_hostname": "localhost", 
        "inventory_hostname_short": "localhost", 
        "mysql_host": "10.0.0.3",
        "mysql_password": "supersecretpassword",
        "mysql_port": 3306,
        "mysql_user": "fred",
        "omit": "__omit_place_holder__1c934a5a224ca1d235ff05eb9bda22044a6fb400", 
        "playbook_dir": "."
    }
}

خروجی تأیید می کند که همه متغیرهایی که ما تنظیم کرده ایم روی هاست اعمال می شوند. با این حال، فایل group_vars/database ما در حال حاضر همه متغیرهای ما را در خود جای می دهد. این بدان معناست که ما می‌توانیم آن را رمزگذاری نشده رها کنیم، که به دلیل متغیر رمز پایگاه داده یک نگرانی امنیتی است، یا همه متغیرها را رمزگذاری کنیم، که باعث ایجاد مشکلاتی در قابلیت استفاده و همکاری می‌شود.

انتقال متغیرهای حساس به Ansible Vault

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

به منظور اعمال متغیرهای بیش از یک فایل، می توان از یک فهرست متغیر به جای فایل متغیر Ansible استفاده کرد. ما می توانیم پیکربندی خود را برای استفاده از این توانایی تغییر دهیم. ابتدا نام فایل موجود را از پایگاه داده به vars تغییر دهید. این فایل متغیر رمزگذاری نشده ما خواهد بود:

mv group_vars/database group_vars/vars

بعد، یک دایرکتوری با همان نام فایل متغیر قدیمی ایجاد کنید. فایل vars را به داخل منتقل کنید:

mkdir group_vars/database
mv group_vars/vars group_vars/database/

ما اکنون به جای یک فایل، یک دایرکتوری متغیر برای گروه پایگاه داده داریم و یک فایل متغیر رمزگذاری نشده داریم. از آنجایی که متغیرهای حساس خود را رمزگذاری خواهیم کرد، باید آنها را از فایل رمزگذاری نشده خود حذف کنیم. برای حذف داده های محرمانه، فایل group_vars/database/vars را ویرایش کنید:

nano group_vars/database/vars

در این صورت می خواهیم متغیر mysql_password را حذف کنیم. اکنون فایل باید به شکل زیر باشد:

group_vars/database/vars

---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

سپس، یک فایل رمزگذاری شده با طاق در دایرکتوری ایجاد کنید که در کنار فایل vars رمزگذاری نشده زندگی می کند:

ansible-vault create group_vars/database/vault

در این فایل متغیرهای حساسی که قبلا در فایل vars وجود داشت را تعریف کنید. از نام متغیرهای یکسانی استفاده کنید، اما رشته vault_ را برای نشان دادن اینکه این متغیرها در فایل محافظت شده توسط vault تعریف شده اند، پیشاپیش قرار دهید:

group_vars/database/vault

---
vault_mysql_password: supersecretpassword

پس از اتمام کار فایل را ذخیره کرده و ببندید.

ساختار دایرکتوری حاصل به این صورت است:

.
├── . . .
├── group_vars/
│   └── database/
│       ├── vars
│       └── vault
└── . . .

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

برای پرداختن به این موضوع، پروژه Ansible به طور کلی رویکرد کمی متفاوت را توصیه می کند.

ارجاع به متغیرهای Vault از متغیرهای رمزگذاری نشده

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

برای نشان دادن، فایل متغیرهای رمزگذاری نشده را دوباره باز کنید:

nano group_vars/database/vars

دوباره متغیر mysql_password را اضافه کنید. این بار، از قالب Jinja2 برای ارجاع به متغیر تعریف شده در فایل محافظت شده از طاق استفاده کنید:

group_vars/database/vars

---
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred

# sensitive data
mysql_password: "{{ vault_mysql_password }}"

متغیر mysql_password به مقدار متغیر vault_mysql_password که در فایل vault تعریف شده تنظیم می شود.

با این روش می توانید با مشاهده فایل group_vars/database/vars، تمامی متغیرهایی را که بر روی هاست های گروه پایگاه داده اعمال می شود، درک کنید. قسمت های حساس توسط قالب Jinja2 محو می شوند. group_vars/database/vault تنها زمانی باید باز شود که خود مقادیر نیاز به مشاهده یا تغییر داشته باشند.

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

ansible -m debug -a ‘var=hostvars[inventory_hostname]’ database

 

Output

localhost | SUCCESS => {
    "hostvars[inventory_hostname]": {
        "ansible_check_mode": false, 
        "ansible_version": {
            "full": "2.2.0.0", 
            "major": 2, 
            "minor": 2, 
            "revision": 0, 
            "string": "2.2.0.0"
        }, 
        "group_names": [
            "database"
        ], 
        "groups": {
            "all": [
                "localhost"
            ], 
            "database": [
                "localhost"
            ], 
            "ungrouped": []
        }, 
        "inventory_dir": "/home/sammy/vault", 
        "inventory_file": "./hosts", 
        "inventory_hostname": "localhost", 
        "inventory_hostname_short": "localhost", 
        "mysql_host": "10.0.0.3",
        "mysql_password": "supersecretpassword",
        "mysql_port": 3306,
        "mysql_user": "fred",
        "omit": "__omit_place_holder__6dd15dda7eddafe98b6226226c7298934f666fc8", 
        "playbook_dir": ".", 
        "vault_mysql_password": "supersecretpassword"
    }
}

هم vault_mysql_password و هم mysql_password قابل دسترسی هستند. این تکرار بی ضرر است و تاثیری در استفاده شما از این سیستم نخواهد داشت.

نتیجه

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

Ansible VaultVPS یا سرور مجازیاتصال به لینوکسخرید سرور مجازیسرور اوبونتو 20.04سرور مجازیسرور مجازی آلمانسرور مجازی آمریکامتغیرهای Vault

 

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

  • behnam gol mohamadi