مجوزهای نرمافزاری اسناد و متون حقوقی هستند که توسط حقوقدانان و کارشناسان حوزه فناوری تدوین میشوند تا شرایط استفاده، تغییر، توسعه و بازنشر یک برنامه یا کد منبع را مشخص کنند.
این متون در قالب چندین بند و تبصره نوشته میشوند و برای توسعهدهندگان و کاربران مشخص میکنند که دقیقاً چه حقوقی در برابر آن کد دارند و پدیدآورنده پروژه چه انتظارات یا شروطی تعیین کرده است.
دستهبندی کلی مجوزهای نرمافزاری
مجوزهای نرمافزاری را میتوان به دو دسته کلی تقسیم کرد:
۱. مجوزهای انحصاری و مالکیتی (Proprietary): در نرمافزارهای تجاری و بسته (مانند سیستمعامل ویندوز یا فتوشاپ)، کاربر صرفاً حق استفاده محدود از برنامه را تحت یک توافقنامه کاربری نهایی (EULA) دریافت میکند. در این حالت، کاربر مالک نرمافزار نیست و حق دسترسی به سورسکد، مهندسی معکوس، تغییر یا بازتوزیع برنامه را ندارد.
نکته فنی-حقوقی: وارد کردن کلید فعالسازی (Product Key) یا فعالسازی آنلاین صرفاً ابزارهای فنی برای مدیریت حقوق دیجیتال و کنترل دسترسی (DRM) هستند و نباید با خودِ سند حقوقی مجوز اشتباه گرفته شوند. مثلاً در اصطلاح رایج «خرید لایسنس ویندوز»، آنچه در عمل مبادله میشود «کلید فعالسازی» است، در حالی که مجوز، همان متن شروط و توافقنامهای است که هنگام نصب میپذیرید.
۲. مجوزهای آزاد و متنباز (Free & Open Source): مجوزهایی مانند GPL، MIT و Apache که به کاربران اجازه میدهند سورسکد برنامه را بخوانند، آن را مطابق نیاز خود تغییر دهند و حتی نسخه جدید را بازنشر کنند.
سه سطح وجود داره: shell، prefetch و navigation، و هر سطح شامل سطحهای قبلیه. این قابلیت فقط با cacheComponents کار میکنه و بدون اون فلگ، بیلد fail میشه. با سطح navigation، چیزهای زیر باعث شکست بیلد میشن:
fetch یا کوئری دیتابیس بدون کش
استفاده از cookies و headers
searchParams سمت سرور
scopeهای use cache با طول عمر کمتر از ۵ دقیقه
پاس دادن promiseهای وابسته به request به کامپوننتهای کلاینت
این خطاها حتی داخل Suspense هم میمونن. مسیرهای داینامیک هم باید generateStaticParams رو با حداقل یه مجموعهی کامل پارامتر export کنن، و این قانون برای generateMetadata هم صدق میکنه. layout فرزند میتونه سطح سختگیرانهتر از والد بذاره ولی ضعیفتر نه. ensureStatic با instant فرق داره؛ instant دربارهی اینه که UI بتونه فوری آپدیت بشه.
navigation() و prefetch()
دو تابع جدید از next/cache هستن که کنترل میدن چی prefetch بشه. navigation رو با await صدا بزنی، زیردرخت پایینش از prefetch بیرون میره و فقط موقع ناوبری واقعی رندر میشه. prefetch هم زیردرخت رو از App Shell مشترک خارج میکنه و فقط موقع Link با prefetch صریح یا ناوبری رندر میشه. هر دو به cacheComponents نیاز دارن. توی نوتهای ریلیز گیتهاب اشاره شده پیشوند unstable از این دو تا برداشته شده، پس ایمپورتشون رو بعد از آپدیت حتماً چک کن.
ابزارهای مخصوص coding agentها
دو قابلیت آزمایشی برای کار با agentها اضافه شده. اولی دستور آپگرید با حالت agentه:
npx next@canary upgrade --agent=latest
سه policy داره: security (پیشفرض، نسخهی آسیبپذیر رو به نزدیکترین نسخهی امن میبره)، latest (به آخرین نسخهی npm میبره) و experimental-future (به latest میبره و راهنمای اتخاذ Cache Components رو هم آماده میکنه). یه نکته: نوتهای ریلیز گیتهاب اسم این فلگ رو ai نوشته و Roboto Studio اسمش رو agent. من نتونستم صفحهی رسمی رو بخونم، پس قبل از استفاده help خود دستور رو چک کن. کانفیگ مکمل هم experimental.agentUpgrade هست که با مقدارهای security، latest یا false، توی next dev و next build یادآوری آپگرید نشون میده.
دومی experimental.agentFeedback هست. به coding agent اجازه میده خطاهای فریمورک، مستندات نامفهوم و workaroundها رو ثبت کنه و پیشنویس گزارش بسازه. تا خودت دکمهی Send feedback رو نزنی چیزی ارسال نمیشه. برای پروژههای جدید create-next-app روشنه، برای پروژههای موجود opt-in هست، تلهمتری Next.js لازم داره و توی CI اجرا نمیشه.
بهبودهای Turbopack
اینها بدون هیچ کانفیگی فعالن:
کش دیسکی ۲۰ تا ۲۵ درصد کوچیکتر شده (Zstandard برای داده و LZ4 برای متادیتا)
HMR سرور بهصورت lazy: بعد از ویرایش یه ماژول مشترک سرور، فقط صفحهی فعلی دوباره کامپایل میشه
یه runtime chunk مشترک برای همهی routeها
باندلهای پروداکشن کوچیکتر با اسمهای کوتاهتر برای کلاسهای CSS Module و export mangling
طبق نوتهای ریلیز، export name mangling حالا برای بیلدهای Turbopack پیشفرضه، پس اگه کدت به اسم export ها وابستهست بعد از آپدیت تستش کن.
React 19.3
React 19.3 طبق گفتهی Roboto Studio ۹ سپتامبر منتشر شده و Next.js 16.4 ازش پشتیبانی میکنه. تغییراتش:
View Transitions پایدار شده، با addTransitionType برای انیمیشنهای جهتدار
Fragment Refs پایدار شده
API پایدار browser که با use(browser()) برای کدهایی که به مقدارهای مخصوص مرورگر نیاز دارن استفاده میشه
پشتیبانی از Trusted Types
رندر Context مستقیم از Server Components بدون Provider
فلگهای آزمایشی
زیر کلید experimental توی next.config.ts اینها اضافه شدن:
turbopackRustReactCompiler: نسخهی Rust کامپایلر React. نویسندهی Roboto Studio ۳۰ درصد حافظهی کمتر و ۱۵ درصد کامپایل سریعتر گزارش کرده، که عدد خودشه و رسمی نیست.
turbopackGc: garbage collection برای دادههای کامپایل قدیمی، هم توی حافظه هم روی دیسک.
turbopackLazyDynamicImports: dynamic importهای سمت کلاینت توی dev فقط موقع اولین درخواست کامپایل میشن. بعضی importهای next/dynamic هنوز eager کامپایل میشن.
turbopackPluginRuntimeStrategy با مقدار workerThreads: Babel، PostCSS و loaderهای webpack رو توی worker thread اجرا میکنه، نه child process. روی Node.js نسخهی 24.13.1 و بالاتر به child process برمیگرده.
turbopackAdditionalRoots: بهش اجازه میده وابستگیهای symlink شده بیرون از ریشهی پروژه رو دنبال کنه، مثلاً پکیجهای لوکال لینکشده یا store سراسری pnpm. فعلاً دستی ست میشه.
بقیهی چیزها: Turbopack Bundle Analyzer حالا خلاصهی بزرگترین routeهای کلاینت، نمای جدولی، snapshot برای مقایسه و جدا کردن مسیر بحرانی رندر از وابستگیهای async رو داره. یه skill هم برای بهینهسازی باندل هست:
طبق نوتهای گیتهاب اینها هم اضافه شدن: گزینهی آزمایشی imgOptMozjpeg برای next/image، ارتقا به web-vitals نسخهی 6 با گزارش soft navigation، و یه entrypoint تایپ به اسم next/cache-handlers.
نکات آپگرید
لیست رسمی breaking change من پیدا نکردم، ولی نوتهای ریلیز چند تغییر مهم دارن: حذف تنظیم experimental.appNewScrollHandler، منسوخ شدن پشتیبانی از React 18 توی Pages Router، فعال شدن strict route matching بهصورت پیشفرض، و حذف unstable_eager. آپگرید پایه:
React رو باید دستی بالا ببری، چون peer range هنوز هر React 19 رو قبول میکنه. توی monorepoها اگه دو کپی Next توی گراف تایپها بود، نویسندهی Roboto Studio با override توی pnpm-workspace.yaml حلش کرد (بعد از اجرای pnpm why next):
overrides:
"next@<16.4.0": 16.4.0
همون نویسنده گزارش داده دستور upgrade با فلگ agent وقتی روی یه زیرپوشه اجرا شد fail شد، چون CLI ایمپورت نسبی توی next.config.ts رو از مسیر اشتباه پیدا میکرد، و اجرا از داخل پوشهی خود اپ جواب داد. اگه Cache Components رو برای یه اپ موجود روشن کنی ممکنه خطا ببینی، و با ensureStatic برابر navigation اون خطاها خطای بیلد میشن.
جمعبندی
اگه پروژهی جدید میسازی، Cache Components از همون اول فعاله و ensureStatic یه راه خوب برای قفل کردن استاتیک بودن صفحههاست. برای پروژهی قدیمی، آپگرید رو بکن ولی Cache Components رو جداگانه و با تست روشن کن. بهبودهای Turbopack بدون هیچ کاری از طرف تو میرسن.
یک اصل مهم: کلمه «آزاد» در نرمافزارهای آزاد به معنای «آزادی عمل در استفاده، مطالعه، تغییر و انتشار» است، نه «رایگان بودن». یک نرمافزار آزاد میتواند کاملاً بهصورت تجاری عرضه شود و توسعهدهنده از فروش نسخهها یا ارائه خدمات پشتیبانی آن درآمدزایی کند.
تفاوت در تدوین متن مجوزها
متون مجوزهای آزاد (مانند GPL یا MIT) اسنادی استاندارد، ثابت و ثبتشده توسط نهادهای مرجع بینالمللی (مانند بنیاد نرمافزار آزاد FSF و بنیاد پیشگامان متنباز OSI) هستند؛ بنابراین یک توسعهدهنده نمیتواند متن آنها را سلیقهای تغییر دهد و همچنان آن را با همان نام معتبر منتشر کند. اما توافقنامههای انحصاری (EULA) توسط وکلای هر شرکت به صورت اختصاصی تدوین میشوند و ممکن است در هر نسخه جدید از نرمافزار دستخوش تغییر شوند.
مفهوم کپیرایت (Copyright) و کپیلفت (Copyleft) در نرمافزار
۱. قانون کپیرایت (Copyright)
قانون کپیرایت یا «حق پدیدآورنده» بهصورت خودکار و پیشفرض بر هر کدی که مینویسید اعمال میشود؛ یعنی حتی اگر هیچ فایلی به عنوان مجوز در مخزن پروژه خود قرار ندهید، کپیرایت آن منحصراً متعلق به شماست و هیچکس بدون اجازه صریح شما حق استفاده، تغییر یا انتشار آن را ندارد.
وضعیت کپیرایت نرمافزار در ایران: در ایران برخلاف تصور عموم، قوانین حمایتی مشخصی وجود دارند؛ از جمله «قانون حمایت از پدیدآورندگان نرمافزارهای رایانهای (مصوب ۱۳۷۹)» و «قانون حمایت از حقوق مؤلفان، مصنفان و هنرمندان (مصوب ۱۳۴۸)». علت تصور اشتباه عموم این است که ایران عضو پیمانهای بینالمللی کپیرایت (مانند کنوانسیون برن) نیست؛ به همین خاطر کدهای توسعهدهندگان خارجی در ایران مشمول حمایت کپیرایت بینالمللی نمیشوند، اما نرمافزارهایی که توسط توسعهدهندگان داخلی پدید آمدهاند، کاملاً تحت حمایت قوانین کپیرایت کشور قرار دارند و بازنشر غیرمجاز آنها قابل پیگرد قضایی است؛ رویکردی که پلتفرمهای پخش فیلم و محصولات بومی نیز برای صیانت از آثار خود به آن استناد میکنند.
۲. مفهوم کپیلفت (Copyleft)
مجوزهای نرمافزاری مستقل از قانون کشورها نیستند؛ بلکه مشروعیت اجرایی خود را مستقیماً از دل همان قانون کپیرایت میگیرند. پدیدآورنده به پشتوانه کپیرایت خود به دیگران اجازه بهرهبرداری میدهد، اما میتواند با سازوکار «کپیلفت» شرط بگذارد که این آزادی تا ابد برای نسخههای بعدی نیز حفظ شود.
از نظر کپیلفت، مجوزهای آزاد نرمافزاری به دو شاخه اصلی تقسیم میشوند:
مجوزهای آسانگیر (Permissive): مانند MIT، BSD و Apache که دست توسعهدهنده بعدی را کاملاً باز میگذارند؛ به طوری که او میتواند کد را تغییر داده و حتی در یک نرمافزار بسته و انحصاری بدون الزام به انتشار سورسکد به کار ببرد.
مجوزهای کپیلفت (Copyleft): مانند GPL که یک شرط اساسی و سفتوسخت دارند: هر پروژه یا کدی که بر پایه این نرمافزار ساخته یا از آن مشتق شود، باید حتماً با همان مجوز آزاد و به همراه سورسکد در اختیار عموم قرار گیرد تا از انحصاریسازی دستاوردهای جمعی جلوگیری شود.
ساختار و بندهای کلیدی یک مجوز نرمافزاری
هر مجوز نرمافزاری استاندارد بندهای خود را در سه دسته کلی تنظیم میکند:
۱. اختیارات و مجوزها (Permissions): چه کارهایی مجاز است؟
استفاده تجاری از کد، اعمال تغییرات، توزیع مجدد و استفاده در پروژههای خصوصی.
۲. شروط و الزامات (Conditions): چه کارهایی را موظفید انجام دهید؟
درج نام پدیدآورنده اصلی و حفظ کپیرایت (Attribution)، قرار دادن متن مجوز اصلی در کنار کدها، و در مجوزهای کپیلفت: الزام به انتشار سورسکد پروژههای مشتقشده.
۳. محدودیتها و سلب مسئولیت (Limitations): چه مسائلی بر عهده سازنده نیست؟
سلب گارانتی و ضمانت عملکرد (یعنی در صورت بروز خطا، آسیب یا باگ، سازنده هیچ مسئولیت مدنی یا مالی ندارد) و منع استفاده تجاری یا تبلیغاتی از نشان و لوگوی توسعهدهنده اصلی.
نمونههای خاص و جالب از مجوزهای نرمافزاری
در کنار مجوزهای رایجی مانند MIT و GPL، نمونههای کمتر شناختهشده و جالبی در دنیای برنامهنویسی وجود دارند:
۱. مجوز WTFPL: مجوزی بسیار کوتاه و ساختارشکن با این پیام: «هر کاری دوست داری با این کد بکن!» این مجوز با وجود لحن غیررسمیاش، توسط بنیاد نرمافزار آزاد (FSF) به عنوان یک مجوز معتبر و سازگار با GPL پذیرفته شده است. (مشاهده متن مجوز)
۲. مجوز بقراط (Hippocratic License): مجوزی با دغدغه اخلاقی و حقوق بشری که استفاده از کدهای نرمافزار را برای اهدافی نظیر نظارت جمعی، صنایع نظامی و سرکوب صراحتاً ممنوع کرده است. (وبسایت پروژه)
۳. مجوز JSON: داگلاس کراکفورد (خالق ساختار JSON) یک جمله ساده به مجوز نرمافزار خود اضافه کرد: «این نرمافزار باید برای کارهای خوب استفاده شود، نه شرورانه!» همین جمله به ظاهر ساده، سالها وکلای شرکتهای بزرگی مثل IBM را به دردسر انداخت؛ زیرا از نظر حقوقی نمیتوانستند تضمین کنند مشتریانشان هیچ کار غیرخوبی با نرمافزار انجام نمیدهند! (مشاهده مجوز JSON)
نکته تخصصی درباره مجوزهای اخلاقی: شاید بپرسید چرا مجوزهایی مثل JSON یا بقراط استاندارد تلقی نمیشوند؟ از نظر مراجع رسمی نرمافزار آزاد و متنباز (FSF و OSI)، یک مجوز استاندارد نباید هیچگونه تبعیضی نسبت به حوزه فعالیت، نوع استفاده یا هویت کاربر قائل شود (آزادی صفرم FSF و بند ششم تعاریف متنباز OSI). به همین دلیل این مجوزها رسماً جزو FOSS دستهبندی نمیشوند.
نحوه انتخاب مجوز برای پروژه نرمافزاری
هنگام انتخاب مجوز برای پروژه خود، دو فاکتور اصلی را مد نظر داشته باشید:
۱. فرهنگ اکوسیستم و زبان برنامهنویسی: اگر برای جامعه خاصی کد میزنید (مثلاً اکوسیستم لینوکس یا فریمورکهای وب)، بهتر است از مجوزهای مرسوم در همان اکوسیستم استفاده کنید تا سایر توسعهدهندگان برای مشارکت و استفاده از کد شما با موانع حقوقی مواجه نشوند.
۲. بررسی سازگاری مجوزها (License Compatibility): اگر در پروژه خود از کتابخانهها یا پکیجهای دیگران استفاده میکنید، حتماً مجوز آنها را بررسی کنید:
اگر کتابخانهای با مجوز GPL اضافه کنید، کل پروژه شما نیز باید تحت مجوز GPL منتشر شود (به دلیل خاصیت سرایتپذیری کپیلفت).
اما اگر از کتابخانههای با مجوزهای آسانگیر مثل MIT یا Apache استفاده کنید، دست شما برای انتخاب پروانه نهایی پروژه خودتان باز خواهد بود.
شرایط تغییر مجوز (Relicensing) و تلههای حقوقی گیتهاب
تغییر مجوز پروژههای مشارکتی: اگر پروژهای تحت مجوزی مانند GPL باشد و چندین برنامهنویس در آن مشارکت کرده باشند، هیچیک از پدیدآورندگان بهتنهایی نمیتواند مجوز کل پروژه را به یک مجوز آسانگیر (مثل MIT) تغییر دهد؛ مگر اینکه از تکتک مشارکتکنندگانی که در کدهای فعلی سهیم بودهاند رضایت مکتوب بگیرد، زیرا حق مؤلف کدها متعلق به تمام تیم توسعه است.
تله ریپوزیتوری عمومی (Public) بدون فایل مجوز: اگر کدهایتان را روی گیتهاب به صورت Public منتشر کنید اما فایلی به عنوان LICENSE در آن قرار ندهید، پروژه شما متنباز (Open Source) نیست! در این حالت حق کپیرایت انحصاری برای شما حفظ شده و دیگران از نظر قانونی حتی حق کپی، فورک و استفاده از کدهای شما را ندارند. در این شرایط اگر فرد دیگری کدی به پروژه شما اضافه کند، پروژه دچار تداخل مالکیتی شده و از نظر حقوقی برای توسعههای آینده قفل میشود.
آزادی فراتر از نرمافزار
مفهوم کپیلفت و اشتراکگذاری آزاد بعدها از دنیای برنامهنویسی به سایر حوزهها نیز راه پیدا کرد:
مجوزهای کریتیو کامنز (Creative Commons): برای آثاری مانند کتاب، متن، تصویر و موسیقی طراحی شدند. برای مثال، کتاب «اِدا و زِنگمَن» (کتابی با موضوع آزادی تکنولوژی) تحت مجوز آزاد CC BY-SA 4.0 منتشر شده است.
مجوز تولید همتا یا PPL (Peer Production License): که با رویکرد Copyfarleft طراحی شده است؛ به این صورت که استفاده از اثر را برای تعاونیها، افراد و نهادهای غیرانتفاعی کاملاً رایگان کرده، اما شرکتهای تجاری را ملزم به پرداخت هزینه میکند (مطالعه بیشتر درباره PPL).
منابع برای تحقیق بیشتر
مقایسه خانواده مجوزهای GPL (شامل GPLv2, GPLv3, AGPL)
یه تست واقعی هم گزارش شده: تیم threat intelligence خود کلادفلر با Clef، دستهبندی دامنهها رو توی ۲.۲ ثانیه انجام داده، در برابر ۴.۷ ثانیه با gpt-oss-120b، یعنی تعداد دستهبندی بیشتر با تقریباً نصف تأخیر.
کجا در دسترسه و قیمت؟
Clef همین الان روی Workers AI از طریق API کلادفلر در دسترسه، و وزنهاش هم با لایسنس Apache 2.0 روی Hugging Face منتشر شدن. قیمتگذاری توی اعلامیه مشخص نشده.
پلتفرم RL برای fine-tune کردن
کنار مدلها، کلادفلر یه سرویس reinforcement learning هم معرفی کرده که با اون مشتریها میتونن Clef رو برای کار مشخص خودشون fine-tune کنن. این پلتفرم از AI Gateway (برای جمعآوری دادهی آموزشی)، Workers AI (برای تولید rollout)، Cloudflare Containers (بهعنوان sandbox RL) و یه ماژول trainer (برای آپدیت وزنها) استفاده میکنه و امکان آوردن مدل شخصی (BYO Model) هم داره. فعلاً fine-tune فقط با همکاری مستقیم مهندسهای کلادفلر انجام میشه و نسخهی self-serve برای بعداً برنامهریزی شده.
کاربردها
کلادفلر کاربردهایی مثل مسیردهی و triage پشتیبانی مشتری، دستهبندی دامنه برای threat intelligence، پردازش فاکتور، دستهبندی حوادث امنیتی، تشخیص fraud و phishing، تشخیص ربات خوب از بد، و ارزیابی گزارشهای Trust and Safety رو نام برده.
چیزهایی که باید با احتیاط بهشون نگاه کرد
همهی اعداد بالا از خود کلادفلر اومدن، و مقایسه با Jev توسط خود کلادفلر انجام شده، نه یه ارزیابی مستقل. قیمت و سقف throughput اعلام نشده، دسترسی به fine-tune فعلاً محدوده، و خود کلادفلر هم اشاره کرده که بخشی از عملکرد به نزدیکی زیرساخت به شبکهی edge کلادفلر بستگی داره. با ورود یه بازیگر به این بزرگی، رقابت توی دستهی مدلهای تصمیمگیر عملاً جدی شده، ولی هنوز باید منتظر تستهای مستقل موند.
تیم Svelte یه دستور migration رسمی داده که تغییرات مکانیکی رو خودکار انجام میده و برای بقیه یه لیست TODO تولید میکنه:
npx sv migrate sveltekit-3 --tasks all --confirm
توصیهی منطقی اینه که این دستور رو روی یه branch تمیز اجرا کنی و diff رو قبل از merge مرور کنی. برای پروژهی جدید هم دستور استاندارد همونه که همیشه بود:
npx sv create my-new-app
چیزی که هنوز نیومده
Remote functions، همون قابلیت RPC تایپسیف بین کلاینت و سرور که خیلیها منتظرش بودن، توی این نسخه هم پایدار نشده. تیم Svelte میگه این قابلیت اولویت اصلیه، ولی چون به Async Svelte وابستهست که فعلاً پشت یه فلگ experimental قرار داره، هنوز باید با فعال کردن اون فلگ ازش استفاده کنی.
یه نکتهی احتیاطی دربارهی نیازمندیها: توی پست release candidate گفته شده بود SvelteKit 3 به Svelte 5 و Vite 8 نیاز داره، ولی پست انتشار نهایی نسخههای حداقل Node، Svelte و Vite رو دوباره ذکر نکرده. قبل از آپدیت، این نیازمندیها رو توی مستندات رسمی هم چک کن.
# خروجی عادی رو دور بنداز، خطاها رو نگه دار
command > /dev/null
# فقط خطاها رو دور بنداز
command 2> /dev/null
# هر دو رو دور بنداز
command > /dev/null 2>&1
# معادل کوتاهتر توی bash
command &> /dev/null
یه نکتهی ظریف: ترتیب ریدایرکت مهمه. توی حالت اول، ابتدا خروجی عادی به null میره و بعد خطاها هم به همون مقصدِ خروجی عادی وصل میشن. اگه ترتیب رو برعکس بنویسی، خطاها هنوز به ترمینال میرن، چون وقتی ریدایرکت خطاها ارزیابی میشه، خروجی عادی هنوز به ترمینال اشاره میکرده:
# درست: هر دو خروجی دور ریخته میشن
command > /dev/null 2>&1
# اشتباه: خطاها هنوز روی ترمینال میان
command 2>&1 > /dev/null
چند کاربرد دیگهش:
# خالی کردن محتوای یه فایل بدون پاک کردنش (مثلاً لاگ)
cat /dev/null > app.log
# فقط بررسی موفقیت یه دستور، بدون چاپ خروجیش
if grep -q "error" app.log 2>/dev/null; then
echo "خطا پیدا شد"
fi
# ساکت کردن یه cron job
0 * * * * /path/to/script.sh > /dev/null 2>&1
/dev/zero، منبع بیپایان صفر
هر بار که ازش بخونی، بایت صفر میده، بینهایت. به درد ساختن فایلهایی با اندازهی مشخص میخوره:
# ساخت یه فایل ۱۰۰ مگابایتی پر از صفر
dd if=/dev/zero of=test.img bs=1M count=100
# ساخت یه swap file ۲ گیگابایتی
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
اگه فقط فایلی با اندازهی مشخص بخوای و لازم نباشه واقعاً صفر روی دیسک نوشته بشه، دستور truncate خیلی سریعتره، چون یه sparse file میسازه که فضاش تا وقتی استفاده نشه اشغال نمیشه:
truncate -s 100M test.img
/dev/urandom و /dev/random، عدد تصادفی
این دو تا بایت تصادفی از مولد اعداد تصادفی کرنل میدن. سالها یه توصیهی رایج بود که random امنتره چون وقتی «آنتروپی» کم باشه بلاک میکنه، و urandom هیچوقت بلاک نمیکنه. ولی توی کرنلهای جدید این تفاوت عملاً از بین رفته: از کرنل ۴.۸ هر دو از یه CSPRNG یکسان تغذیه میشن، و از کرنل ۵.۶ به بعد random فقط تا زمانی که مولد موقع بوت اولیهسازی بشه بلاک میکنه. برای تقریباً هر کاربرد عملی، urandom انتخاب درسته.
# ۳۲ بایت تصادفی، بهصورت base64
head -c 32 /dev/urandom | base64
# رشتهی hex برای secret یا token
head -c 16 /dev/urandom | xxd -p
# یه پسورد ۲۴ کاراکتری فقط با حروف و عدد
tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 24; echo
# معادل با openssl، اگه نصب باشه
openssl rand -base64 32
یه استفادهی دیگهش پر کردن دیسک با دادهی تصادفی قبل از رمزنگاری یا دور انداختنشه، ولی اینجا باید حواست باشه: روی SSD و فلش، پاکسازی با overwrite بهخاطر wear leveling تضمینشده نیست، و این روش بیشتر برای هارد مکانیکی معنی داره.
/dev/full، دیسک همیشه پر
این یکی کمکاربردتره ولی برای تست جالبه: هر نوشتنی توش با خطای «No space left on device» شکست میخوره. برای اینکه ببینی برنامهت موقع پر شدن دیسک درست رفتار میکنه یا نه:
echo "test" > /dev/full
# bash: echo: write error: No space left on device
/dev/stdin، /dev/stdout و /dev/stderr
این سه تا در واقع symlink به file descriptor های استاندارد پروسس فعلی هستن:
کاربردش وقتیه که یه برنامه فقط اسم فایل میگیره و تو میخوای ورودی یا خروجی استاندارد رو بهش بدی:
# پیام خطا رو به stderr بفرست
echo "یه مشکلی پیش اومد" > /dev/stderr
# فایل رو از stdin بخون، وقتی برنامه فقط مسیر فایل قبول میکنه
cat file.txt | some-tool --input /dev/stdin
/dev/tty، ترمینال واقعی
وقتی ورودی یه اسکریپت از pipe میاد، دیگه نمیتونی از کاربر ورودی بگیری. فایل tty همیشه به ترمینال کنترلکنندهی پروسس اشاره میکنه، حتی وقتی ورودی و خروجی ریدایرکت شدن. برای همین ابزارهایی مثل ssh و sudo پسورد رو از همینجا میخونن:
دیسکها و پارتیشنها هم توی همین پوشهان. اسمگذاریشون این شکلیه:
/dev/sda, /dev/sda1 دیسک و پارتیشن SATA
/dev/nvme0n1, /dev/nvme0n1p1 دیسک و پارتیشن NVMe
قبل از هر کاری روشون، با lsblk و blkid مطمئن شو داری با دستگاه درست کار میکنی:
lsblk
blkid
اسم این دستگاهها ممکنه بعد از ریبوت یا وصل کردن یه دیسک جدید عوض بشه، برای همین توی fstab و اسکریپتها بهتره از مسیرهای پایدار استفاده کنی:
/dev/disk/by-uuid/
/dev/disk/by-id/
یه هشدار جدی: dd یکی از خطرناکترین ابزارهای لینوکسه چون هیچ تأییدی نمیگیره. اگه توی مقصد اسم دیسک اشتباه رو بنویسی، دادهت بدون برگشت پاک میشه. قبل از اجرا، مقصد رو دوباره چک کن:
# نوشتن یه ISO روی فلش (مطمئن شو sdX درسته!)
sudo dd if=ubuntu.iso of=/dev/sdX bs=4M status=progress conv=fsync
چند فایل دیگه که ارزش شناختن دارن
اینها فایلهای دیگهای هستن که گاهی سر راهت قرار میگیرن:
/dev/shm یه tmpfs توی RAM؛ برای فایلهای موقت خیلی سریع و shared memory
/dev/loop* وصل کردن یه فایل معمولی بهعنوان بلاک دیوایس (برای mount کردن image)
/dev/pts/* ترمینالهای مجازی (SSH، tmux و ...)
/dev/kmsg پیامهای لاگ کرنل؛ دستور dmesg از همین میخونه
/dev/fuse لازم برای فایلسیستمهای userspace مثل sshfs
/dev/kvm دسترسی به مجازیسازی سختافزاری برای QEMU/KVM
یه چیز جالب هم هست که واقعاً فایل نیست: مسیرهای tcp و udp زیر dev ویژگی خود bash هستن، نه یه فایل واقعی. با اینها میتونی بدون netcat یا curl یه پورت رو چک کنی:
# بررسی باز بودن پورت ۴۴۳ بدون هیچ ابزار اضافه
timeout 3 bash -c '</dev/tcp/example.com/443' && echo "باز است" || echo "بسته است"
اگه اتفاقی /dev/null رو پاک کردی
این اتفاق از چیزی که فکر میکنی رایجتره (مثلاً با یه ریدایرکت اشتباه یا یه اسکریپت بد). اگه null یه فایل معمولی شد یا پاک شد، خیلی از برنامهها عجیب رفتار میکنن. برای بازسازیش:
اون آخرین بخش دستور، همون character device با major برابر ۱ و minor برابر ۳ هست که قبلاً دیدیم. برای بقیه هم همین الگو برقراره:
/dev/null c 1 3
/dev/zero c 1 5
/dev/full c 1 7
/dev/random c 1 8
/dev/urandom c 1 9
جمعبندی
اگه بخوای از این مقاله فقط چند چیز رو به یاد داشته باشی: null برای دور ریختن خروجی (با دقت به ترتیب ریدایرکت)، zero برای ساختن فایلهای پر از صفر، urandom برای تولید secret و رشتهی تصادفی، tty برای گرفتن ورودی از کاربر وسط pipe، و همیشه قبل از هر dd روی دیسک، یه بار دیگه با lsblk مطمئن شو داری روی دیسک درست مینویسی.
عدد ۷۶.۶٪ مال checkpoint ای هست که روی خود split آموزشی همون بنچمارک fine-tune شده؛ مدل پایهی zero-shot فقط ۳۶.۲٪ گرفته، که حتی از baseline اکثریت (۴۶.۱٪) هم پایینتره.
مقایسهی سرعت، یه inference لوکال روی GPU گرمشده رو با یه فراخوانی API میزبانیشده (که زمان شبکه رو هم شامل میشه) مقایسه میکنه — یعنی سیب و پرتقال.
روی Banking77 که باید بین ۷۷ برچسب intent انتخاب کنی، Jev عدد ۰.۸۷۰ گرفته و Laya فقط ۰.۴۲۵؛ یعنی روی دستهبندیهای با تعداد برچسب بالا، Jev فاصلهی زیادی داره و برای Laya باید سلسلهمراتب coarse-to-fine بسازی.
خود مدلکارت Laya هشدار میده که مدل تا وقتی temperature ش دوباره calibrate نشه، بیشازحد مطمئن (overconfident) خروجی میده — که برای مدلی که ارزشش توی احتمالهای واقعیه، یه نکتهی کوچیک نیست.
یه تست مستقل که هر دو مدل رو روی یه مجموعهی ۴۰۰ تصمیمی و توی یه harness یکسان اجرا کرده، نتیجهی متعادلتری داده: Laya روی دو تا از شش سؤال جلو بوده و توی بقیه Jev برتری داشته. سرعت Laya روی مک بین ۲۰ تا ۵۰ میلیثانیه بوده که واقعاً چشمگیره، ولی دقتش بهطور کلی پایینتر از Jev بوده.
مقایسهی سریع
Jev
Laya
نحوهی ارائه
API میزبانیشده، وزنهای بسته، early access
وزنهای باز (Apache-2.0)، اجرای لوکال
هزینه
حدود ۰.۰۴۲ دلار به ازای هر میلیون توکن ورودی
صفر به ازای هر توکن (فقط هزینهی سختافزار خودت)
تأخیر
چند ده تا چند صد میلیثانیه (شامل شبکه)
۲۰ تا ۵۰ میلیثانیه لوکال
دقت out-of-the-box
بالاتر، مخصوصاً با برچسبهای زیاد
پایینتر بدون fine-tune
زبان
متن انگلیسیمحور
نسخهی چندزبانه با بیش از ۱۰۰ زبان
شخصیسازی
ندارد
میتونی fine-tune و calibrate کنی
داده
باید به API بفرستی
داده هیچوقت از ماشین خودت خارج نمیشه
پس کدوم رو استفاده کنیم؟
جواب صادقانه اینه که اینها جایگزین هم نیستن، دو تا ابزار برای دو تا موقعیت متفاوتن. اگه دقت روی برچسبهای زیاد یا سؤالهای پیچیدهتر براش مهمه، نمیخوای زیرساخت اجرای مدل رو خودت نگه داری، و ارسال داده به یه API خارجی مشکلی نداره، Jev هنوز انتخاب امنتریه. ولی اگه دادههات حساسن و نباید از سرورت خارج بشن، حجم فراخوانی اونقدر بالاست که حتی هزینهی ناچیز به ازای هر توکن هم جمع میشه، تأخیر چنددهمیلیثانیهای برات حیاتیه (مثلاً یه حلقهی کنترل real-time)، یا با متن چندزبانه کار میکنی، Laya قابلتوجهتره — به شرط اینکه حاضر باشی یه مقدار وقت برای fine-tune و calibrate کردنش بذاری.
پیشنهاد عملی من اینه که به هیچکدوم از اعداد منتشرشدهی هیچطرفی تکیه نکنی: ۲۰۰ تا ۵۰۰ نمونهی واقعی از دادهی خودت جمع کن، برچسبگذاریشون کن، و هر دو مدل رو روی همونها امتحان کن. چون Laya رایگانه و توی چند دقیقه نصب میشه، این تست تقریباً بیهزینهست، و نتیجهش خیلی بیشتر از هر بنچمارک عمومی به کارت میاد. اگه Laya روی دادهی تو به دقت قابلقبولی رسید، یه مدل لوکال رایگان با تأخیر چنددهمیلیثانیهای ارزش جدی داره؛ اگه نرسید، هزینهی Jev احتمالاً همچنان از خطاهای اضافی ارزونتره.