آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

دستورات و شناسه‌ ها




دستورات و شناسه‌ها

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

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

فرض کنیم شما در یک دایرکتوری خالی هستید. (اگر می‌خواهید این کد را امتحان کنید می‌توانید دایرکتوری به نام test را با اجرای: mkdir test ; cd test ایجاد کنید و داخل آن بروید).

$ ls #لیست فایل‌ها در دایرکتوری جاری(بدون خروجی: فایلی موجود نیست).
$ touch a b c #فایل‌های 'a' و 'b' و 'c' را ایجاد می‌کند.
$ ls #دوباره لیست فایل‌ها، این دفعه در خروجی سه فایل ایجاد شده نمایش داده می‌شود.
a b c

touchیک برنامه کاربردی است که زمان آخرین ویرایش یک فایل معین را به زمان حال تغییر می‌دهد. اگر فایل نامبرده در حال حاضر موجود نباشد، به سادگی آن را، به عنوان یک فایل جدید خالی ایجاد می‌کند . در این مثال، ما سه شناسه به آن داده‌ایم. touch برای هر یک از آنها یک فایل ایجاد می‌کند. فرمان ls سه فایل ایجاد شده را به ما نشان می‌دهد.

$ rm * # تمام فایل‌های دایرکتوری فعلی را حذف می‌کند
$ ls
$ # لیست فایل‌های دایرکتوری جاری(فایل موجود نیست)
$ touch a b c # فایل‌های a و b و c را ایجاد می‌کند
$ ls # دوباره لیست فایل‌ها، این دفعه فایل‌های a و b و c در خروجی نمایش داده می‌شود.
a b c

rm ابزاری برای حذف فایل‌هایی می‌باشد که به عنوان شناسه به آن داده شده‌اند. * یک جانشین (glob) می‌باشد. و در اینجا در اصل به معنای تمام فایل‌های موجود در دایرکتوری جاری می‌باشد. بعداً بیشتر درباره جانشین‌ها (globs) خواهید خواند.

حالا توجه نمودید که بین a و b و همچنین مابین b و c چند تا فاصله وجود داشت؟ همین‌طور نیز متوجه شدید که نتیجه، یعنی فایل‌های ایجاد شده توسط touch با دفعه قبل که فقط یک فاصله بین آنها بود تفاوتی ندارد. حال آگاه شدید که تعداد فضاهای سفید بین شناسه‌ها اهمیت ندارد. دانستن این مطلب با اهمیت است. برای مثال:

    $ echo This is a test.

    This is a test.
    $ echo This    is    a    test.
    This is a test.

echo دستوری است که شناسه‌هایش را در خروجی استاندارد (که در این حالت ترمینال است) می‌نویسد. در این مثال، ما دستور echo را با چهار شناسه به کار برده‌ایم: 'This'و 'is'و 'a' و 'test.' که فرمان echo این شناسه‌ها را می‌گیرد، وآنها را یک به یک با یک فاصله مابین آنها در خروجی چاپ می‌کند. در حالت دوم دقیقاً همان اتفاق رخ می‌دهد. فاصله‌های اضافی تفاوتی ایجاد نمی‌کنند. اگر واقعاً فاصله‌های اضافی را خواسته باشیم، لازم است جمله را به صورت یک شناسه منفرد به آن بدهیم. می‌توانیم این کار را با استفاده از نقل‌قول‌ها انجام بدهیم:

    $ echo "This    is    a    test."
    This    is    a    test.

نقل‌قول‌ها هر چیز در داخلشان را به صورت یک شناسه منفرد بسته‌بندی می‌کنند. این شناسه منفرد ‎ 'This    is    a    test.'‎ می‌باشد، با فاصله‌های صحیح. توجه داشته باشید که نقل‌قول‌ها بخشی از شناسه نیستند، BASH قبل از تحویل شناسه به فرمان echo آنها را حذف می‌کند. echoاین شناسه منفرد را درخروجی چاپ می‌کند، درست مانند آنچه همیشه انجام می‌دهد

در اجتناب از موارد ذیل دقیق باشید:

$ ls # لیست فایل‌های دایرکتوری جاری.
The secret voice in your head.mp3 secret
$ rm The secret voice in your head.mp3 # فرمان rm را با 6 شناسه اجرا می‌کند، نه با یکی!
rm: cannot remove `The': No such file or directory rm: cannot remove `voice': No such file or directory rm: cannot remove `in': No such file or directory rm: cannot remove `your': No such file or directory rm: cannot remove `head.mp3': No such file or directory
$ ls # لیست فایل‌های دایرکتوری جاری: فایل مورد نظر هنوز آنجاست.
The secret voice in your head.mp3 # اما فایل secret شما حالا دیگر نیست!

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

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

    $ [-f file]

شما می‌خواهید دستور ‎ [‎ از شناسه‌های ‎ -f‎، ‎file‎ و ‎]‎ جدا شود. اگر شما ‎ [‎ و ‎-f‎ را با فاصله از یکدیگر جدا نکنید، BASH تصور می‌کند شما می‌خواهید دستوری به نام ‎ [-f‎ را اجرا کنید، و در PATH شما برای برنامه‌ای با نام ‎ [-f‎ جستجو می‌کند. علاوه بر این، شناسه file و ‎]‎ نیز لازم است با فاصله جدا شوند. فرمان ‎[ ‎  انتظار دارد آخرین شناسه‌اش، ‎ ]‎ باشد. در دستور صحیح همه شناسه‌ها با فاصله از یکدیگر جدا می‌شوند:

    $ [ -f file ]

( ما فرمان ‎ [‎ را در آینده مفصل‌تر شرح خواهیم داد. افراد زیادی را دیده‌ایم که با آن سر در گم شده‌اند، و گمان برده‌اند که می‌توان از فضای سفید میان آن و شناسه‌هایش صرفنظر نمود، بنابراین، لازم دانستیم خیلی زود در این مثال خاص آن را مطرح کنیم.)

و البته اگر نام فایل شما شامل فضای سفید و یا دیگر کاراکترهای خاص باشد، باید نقل‌قولی بشود:

    $ [ -f "my file" ]

توجه: لطفاً اگر هنوز مطلب برای شما خیلی واضح نیست، از شناسه‌ها، نقل‌قول‌ها، تفکیک کلمه و http://wiki.bash-hackers.org/syntax/words دید خوبی در این موارد حاصل نمایید. این مهم است که شما قبل از ادامه این راهنما، درک مناسبی از اینکه شل دستوراتی را که به آن می‌دهید چگونه تفسیر می‌کند، داشته باشید.


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



  • شناسه‌ها: اینها کلمات اختیاری اضافه‌ای هستند که می‌توانید موقع اجرای فرمان‌ها تعیین کنید. آنها پس از نام فرمان‌ها آورده می‌شوند(‎'ls -l  foo'‎ فرمان ls را با دو شناسه اجرا می‌کند).

  • نقل‌قول‌ها: دو نوع نقل‌قول( ' و ") برای محافظت از کاراکترهای خاص معین در داخل عبارت نقل‌قولی، از تفسیر شدن به عنوان کاراکتر خاص توسط BASH، استفاده می‌کنیم. تفاوت بین ' و " را بعداً صحبت خواهیم نمود.


انواع دستورات

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

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

      $ nmap -P0 -A --osscan_limit 192.168.0.1

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

      $ alias nmapp='nmap -P0 -A --osscan_limit'
      $ nmapp 192.168.0.1

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

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

  • دستورات داخلی: BASH تعدادی دستور اصلی در ساختمان خودش دارد، از قبیل cd (تغییر دایرکتوری)، echo (نوشتن خروجی)، وغیره. می‌توانید آنها را به عنوان توابعی که از قبل فراهم شده‌اند در نظر بگیرید.

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

      $ [ a < b ]
    
     -bash: b: No such file or directory
      $ [[ a < b ]]

    مثال اول یک خطا باز می‌گرداند، زیرا bash سعی می‌کند فایل b را به دستور [ a ] تغییر مسیر بدهد(بخش تغییر مسیر فایل را ملاحظه کنید) مثال دوم به طور واقعی آنچه شما انتظار دارید انجام می‌دهد. کاراکتر ‎<‎ وقتی که با یک فرمان ‎[[‎ به کار می‌رود، دیگر معنی خاص عملگرتغییر مسیر را ندارد.

  • اجرایی‌ها: آخرین نوع دستوری که می‌تواند توسط bash اجرا بشود، یک دستور اجرایی است، که همچنین یک دستور خارجی یا برنامه‌کاربردی نیز نامیده می‌شود. اجرایی‌ها با استفاده از نام مسیر فراخوانی می‌شوند. اگر فایل اجرایی در دایرکتوری جاری است، به صورت ‎ ./myprogram‎ به کار ببرید. اگر در دایرکتوری ‎ /usr/local/bin‎ است، از ‎/usr/local/bin/myprogram‎ استفاده کنید.

    برای اندکی آسان‌تر نمودن زندگی شما، به‌هرحال، BASH از متغیری استفاده می‌کند، که بگوید در مواقعی که شما فقط نام برنامه کاربردی را می‌دانید و نه نام مسیرکامل آنرا، در کجا برنامه را پیدا کند. این متغیر PATH نام دارد، ومجموعه‌ای از نام مسیرهای دایرکتوری است که با کاراکتر کولن از هم جدا شده‌اند-- به عنوان مثال ‎ /bin:/usr/bin‎ موقعی که یک فرمان بدون نام مسیر در BASH مشخص می‌شود ( مثل myprgram، یا ls)، و یک مستعار، تابع، کلمه کلیدی یا دستور داخلی نباشد BASH در میان دایرکتوری‌های PATH به ترتیب از چپ به راست آنرا جستجو می‌کند، که ببیند آیا آنها دارای فایل اجرایی با نامی که تایپ کرده‌اید، هستند.


  • نکته:
    می‌توانید از فرمان type برای پی‌بردن به نوع یک فرمان استفاده کنید.
    به عنوان مثال:

    $ type rm
    rm is hashed (/bin/rm)

    $ type cd
    cd is a shell builtin




  • مستعارها: یک نام که به یک رشته نسبت داده شده است. موقعی که نام به عنوان یک فرمان به کار برود، با رشته نسبت داده شده تعویض می‌گردد.

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

  • دستورات داخلی: فرمان‌های معینی که در داخل BASH ساخته شده‌اند. اینها موقعی که در خط‌فرمان اجرا شوند به طور داخلی اجرا می‌شوند( و پردازش جدیدی ایجاد نمی‌کنند ).

  • برنامه‌های کاربردی: یک برنامه که می‌تواند با ارجاع به نام مسیر آن اجرا شود(‎/bin/ls‎)، و یا اگر محل استقرار آن در متغیر PATH شما وجود دارد، با نام آن اجرا گردد.


اسکریپت ها

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

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

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

    #!/usr/bin/env bash

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

لطفاً با مثال‌های موجود در اینترنب که از ‎ /bin/sh‎ به عنوان مفسر استفاده می‌کنند فریب نخورید. sh همان bash نیست. هرچند که، دستور زبان sh و bash خیلی همسان به نظر برسند، و ولواینکه اکثر اسکریپت‌های bash در پوسته sh اجرا خواهند شد، مقدار زیادی از مثال‌های این راهنما فقط برای bash تهیه شده‌اند و در sh در می‌مانند و یا رفتار غیر منتظره‌ای خواهند داشت.

همچنین، خواهشمند است از دادن پسوند گمراه کننده ‎ .sh‎ به اسکریپت‌هایتان خودداری نمایید. چون مقصود را برآورده نمی‌کند و کاملاً گمراه کننده است(چون قرار است اسکریپت bash باشد، نه یک اسکریپت sh ).

و در ضمن اگر از Windows برای نوشتن اسکریپت‌هایتان استفاده می‌کنید، در هرحال از کاربرد Notepad برای نوشتن اسکریپت اجتناب نمایید. Microsoft Notepad فقط می‌تواند فایل‌های با انتهای سطر به روش DOS ایجاد نماید. یعنی هر سطری که در notepad ایجاد می‌کنید با دو کاراکتر خاتمه می‌یابد: یک کاراکتر رفتن سر سطر و یک کاراکتر سطرجدید. BASH فقط سطرهایی که به یک کاراکتر سطرجدید خاتمه می‌یابند را می‌خواند. در نتیجه، کاراکتر رفتن سرسطرCarriage Return وقتی که نمی‌دانید آن‌جا هست باعث دردسر باور نکردنی شما خواهد شد( پیغام خطاهای خیلی مرموز). در هر حالت ازویرایشگر محبوبی مانند Vimو Emacsو kate و GEdit و GVIM یا xemacs استفاده کنید. اگر چنین نکنید، بعد قبل از اجرای اسکریپت لازم است تمام کاراکترهای CR( رفتن سرسطر) را پاک کنید.

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

    $ bash myscript

در این مثال، ما BASH را اجرا کرده‌ و به او می‌گوییم اسکریپت ما را بخواند، سطر ‎#!‎ فقط یک توضیح است. BASH به هیچ وجه کاری با آن نمی‌کند.

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

    $ chmod +x myscript
    $ ./myscript

موقعی که اسکریپت به این روش اجرا می‌شود، سطر !# به سیستم عامل (OS) می‌گوید، که از چه مفسری استفاده کند. سیستم عامل ‎ /usr/bin/env‎ را برای اجرای bash به کار می‌برد، و آن هم اسکریپت ما را می‌خواند. BASH خودش از سطر سرآیند # چشم‌پوشی می‌کند.

بعضی‌ها مایل هستند اسکریپت‌های خود را در یک دایرکتوری شخصی نگهداری نمایند. دیگرانی مایل می‌باشند اسکریپت‌هایشان را در محلی که در متغیر PATH ذکر شده نگهداری کنند، اکثراًهر دو را با هم انجام می‌دهند. آنچه من به شما پیشنهاد می‌دهم چنین است:

    $ mkdir -p "$HOME/bin"

    $ echo 'PATH="$HOME/bin:$PATH"' >> "$HOME/.bashrc"

    $ exec bash

دستور اول، دایرکتوری با نام bin را در دایرکتوری خانگی شما ایجاد می‌کند. یک سنت است که دایرکتوری‌های شامل دستورات bin نامیده شوند، حتی وقتی‌که آن دستورات اسکریپت هستند نه برنامه‌های ترجمه شده به زبان ماشین ("باینری"). با دستور دوم یک سطر به فایل ‎ .bashrc‎ شما اضافه می‌شود، که دایرکتوری ایجاد شده را به ابتدای متغیر PATH اضافه می‌کند. حالا هر اجرای جدیدی از BASH برای یافتن اسکریپت‌های اجرایی، دایرکتوری bin شما را بررسی می‌کند. سرانجام، سطر سوم اجرای فعلی BASH ما را با یک نمونه جدید تعویض می‌کند، که فایل ‎ .bashrc‎ جدید را می‌خواند.

تغییرات در DotFiles (از قبیل ‎ .bashrc‎) هرگز بلافاصله تأثیر نمی‌کنند.باید برخی اقدام‌ها را برای حواندن مجدد فایل انجام دهید. در مثال فوق، از ‎ exec bash‎ برای تعویض پوسته در حال اجرا استفاده نمودیم. اگر خواسته باشید، می‌توانید ترمینال باز را بسته وترمینال جدیدی باز کنید. در این حالت BASH دوباره با خواندن فایل ‎ .bashrc‎( و احتمالاً سایر فایل‌ها ) خودش را مقدار دهی مجدد می‌کند. یا، می‌توانید فقط دستور ذکر شده را در خط‌فرمان به کار ببرید ‎ (PATH="$HOME/bin:$PATH")‎ و یا فایل ‎ .bashrc‎ به طور دستی در پوسته جاری با استفاده از ‎source "$HOME/.bashrc"‎ اجرا نمایید.

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

    $ mv myscript "$HOME/bin" 

    $ myscript


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

    
        #!/usr/bin/env bash
        #
        #   شناسه ها  نام اسکریپت  ‎
        #
        # .توضیح کوتاهی در تشریح هدف اسکریپت
        #
        # Copyright [date], [name]


  • نکته:
    می‌توانید سرآیند را با یک کلمه از شناسه‌های اختیاری که می‌خواهید به مفسر ارسال کنید به کار ببرید. به عنوان مثال، شناسه‌های زیر اشکالزدایی تفصیلی را فعال می‌کنند:

        #!/bin/bash -xv
  • لیکن دانستن آنکه Bash کجا نصب گردیده، لازم است، و همیشه هم در ‎ /bin‎ نیست. متأسفانه نمی‌توانید از این یکی استفاده کنید:

        #!/usr/bin/env bash -xv
  • به علت آنکه برای آن، دو کلمه در سرآیند لازم است. یونیکس آن را اجازه نمی‌دهد.می‌توانید به جای آن این‌طور بنویسید:

        #!/usr/bin/env bash
    
        set -xv
  • برای جزئیات بیشتر بخش اشکال‌زدایی را ملاحظه کنید.


  • سرآیند: سرآیند یک اسکریپت برنامه کاربردی که به عنوان مفسر عمل خواهد نمود، را تعیین می‌کند( ماننذ bash و sh و perl و ...). به طور مصطلح یک shebang نیز نامیده می‌شود-- یک عبارت عامیانه که از ترکیب hash (#) و bang(!) می‌آید. شاید ببینید که کلمه shebang خیلی بیشتر از header استفاده می‌شود، به‌ویژه چون سرآیند چند معنی دیگر در زمینه‌های متفاوت دارد، حال آنکه shebang فقط یک معنی دارد.

نظرات 0 + ارسال نظر
ایمیل شما بعد از ثبت نمایش داده نخواهد شد