
نسخهٔ فرمان خطی همیشه نسخهٔ برنامه نیست
صفحهٔ رسمی دریافت اوپناساسال، انتشار نسخهٔ ۴٫۱٫۰ را در ۲۳ اکتبر ۲۰۲۶ ثبت کرده است. نقشهٔ راه رسمی نیز برای شاخههای مختلف دورههای پشتیبانی متفاوت نشان میدهد؛ همهٔ آنها پشتیبانی بلندمدت ندارند. این مقاله با بازبینی ۲۷ اکتبر، روش تشخیص کتابخانهٔ واقعی و بررسی تقویم را توضیح میدهد. صرف دیدن یک نسخهٔ جدید در خبرها، دلیل کافی برای جایگزینی کتابخانهٔ یک سرویس موجود نیست.
ممکن است فرمان سیستم، مفسر پایتون، سرویس وب و یک کانتینر هرکدام به نسخهٔ متفاوتی متصل باشند. به همین دلیل ابزار موجودی، نسخهٔ کتابخانهٔ متصل به پایتون را جدا از خروجی فرمان ثبت میکند. این دو خروجی لزوماً باید یکسان نباشند. برای بررسی یک برنامهٔ دیگر، شواهد را از همان فرایند یا بستهٔ هدف بگیرید؛ موجودی لپتاپ مدیر، وضعیت کتابخانهٔ در حال اجرای سرور را ثابت نمیکند.
تقویم پشتیبانی و تفاوت ساخت فروشنده
سیاست نمونه، چند شاخهٔ بازبینیشده را با تاریخ پایان پشتیبانی ثبت میکند و بعد از پایان مهلت خود، نیاز به بررسی دوباره دارد. ساخت نامرتبط یا قالب نسخهٔ ناشناخته حدس زده نمیشود. همچنین پشتیبانی بالادستی با وصلههای بازگردانیشدهٔ یک توزیع یکسان نیست. تصمیم نهایی دربارهٔ بستهٔ سیستم باید اطلاعیهٔ فروشنده، نسخهٔ بسته و سازگاری برنامه را هم در نظر بگیرد؛ شمارهٔ کتابخانه تنها بخشی از شواهد است.
چهار فایل را کنار هم ذخیره و python -m unittest test_version.py را اجرا کنید. آزمونها شاخهٔ پایانیافته، شاخهٔ نزدیک پایان، نسخهٔ بازبینیشده، ساخت ناشناخته و انقضای سیاست را پوشش میدهند. سپس python inventory_ssl.py > ssl-inventory.json و python check_version.py ssl-inventory.json را اجرا کنید. اگر فرمان اوپناساسال نصب نباشد، بخش خط فرمان تهی میماند، اما نسخهٔ کتابخانهٔ پایتون همچنان گزارش میشود.
گزارش وضعیت پشتیبانی، آزمون زنجیرهٔ گواهی یا سلامت همهٔ الگوریتمهای مورد استفادهٔ برنامه نیست. پس از انتخاب مسیر ارتقا، اتصالهای واقعی، اعتبارسنجی نام میزبان، بستههای بومی و رفتار کتابخانهٔ مصرفکننده را در محیط جدا بررسی کنید. فایلهای نمونه هیچ کتابخانهای نصب یا تعویض نمیکنند. پذیرفتهشدن یک شاخه در سیاست، به معنی داشتن آخرین وصله یا تأیید همهٔ تنظیمات امنیتی سرویس نیست.
فایلهای کامل و قابل اجرا
چهار فایل زیر کاملاند؛ پیشنیاز، ترتیب اجرا و روش بررسی در متن آمده است. کدها خلاصه یا پنهان نشدهاند.
1. فایل کامل inventory_ssl.py
این فایل را با همین نام و بدون حذف سطرها کنار بقیهٔ فایلها ذخیره کنید.
import json
import ssl
import subprocess
def inventory():
result = {'pythonLibrary': ssl.OPENSSL_VERSION, 'commandLine': None}
try:
command = subprocess.run(['openssl', 'version'], check=True, capture_output=True, text=True, timeout=5)
result['commandLine'] = command.stdout.strip()
except (OSError, subprocess.SubprocessError):
pass
return result
if __name__ == '__main__': print(json.dumps(inventory()))دستور اجرا، نتیجهٔ مورد انتظار و محدودیت این فایل در بخش اجرای مقاله توضیح داده شده است.
2. فایل کامل support_policy.json
این فایل را با همین نام و بدون حذف سطرها کنار بقیهٔ فایلها ذخیره کنید.
{
"reviewed": "2026-10-27",
"reviewBy": "2026-11-10",
"source": "https://www.openssl-library.org/roadmap/",
"branches": {
"3.4": {"until": "2026-10-22", "type": "non-LTS"},
"3.5": {"until": "2030-04-08", "type": "LTS"},
"3.6": {"until": "2026-11-01", "type": "non-LTS"},
"4.0": {"until": "2027-05-14", "type": "non-LTS"},
"4.1": {"until": "2027-11-23", "type": "non-LTS"}
}
}دستور اجرا، نتیجهٔ مورد انتظار و محدودیت این فایل در بخش اجرای مقاله توضیح داده شده است.
3. فایل کامل check_version.py
این فایل را با همین نام و بدون حذف سطرها کنار بقیهٔ فایلها ذخیره کنید.
from datetime import date
import json
from pathlib import Path
import re
import sys
def assess(version, policy, today):
if not date.fromisoformat(policy['reviewed']) <= today <= date.fromisoformat(policy['reviewBy']):
return 'review-policy-date'
match = re.match(r'^OpenSSL (\d+\.\d+)\.\d+(?:\s|$)', version or '')
branch = policy['branches'].get(match[1]) if match else None
if branch is None:
return 'unknown-build-review-vendor'
remaining = (date.fromisoformat(branch['until']) - today).days
if remaining < 0: return 'upstream-support-ended-review-vendor'
if remaining <= 30: return 'upstream-support-ending-plan-migration'
return 'supported-branch-check-patches-and-application'
if __name__ == '__main__':
data = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
policy = json.loads(Path(__file__).with_name('support_policy.json').read_text())
print(json.dumps({name: assess(version, policy, date.today()) for name, version in data.items()}))دستور اجرا، نتیجهٔ مورد انتظار و محدودیت این فایل در بخش اجرای مقاله توضیح داده شده است.
4. فایل کامل test_version.py
این فایل را با همین نام و بدون حذف سطرها کنار بقیهٔ فایلها ذخیره کنید.
from datetime import date
import json
from pathlib import Path
import unittest
from check_version import assess
class OpenSSLTests(unittest.TestCase):
def test_lifecycle_and_unknown_build(self):
policy = json.loads(Path(__file__).with_name('support_policy.json').read_text())
today = date(2026, 10, 27)
self.assertIn('ended', assess('OpenSSL 3.4.8 29 Sep 2026', policy, today))
self.assertIn('ending', assess('OpenSSL 3.6.5 29 Sep 2026', policy, today))
self.assertIn('supported-branch', assess('OpenSSL 4.1.0 23 Oct 2026', policy, today))
self.assertIn('unknown-build', assess('LibreSSL 4.0', policy, today))
self.assertEqual(assess('OpenSSL 4.1.0', policy, date(2026, 11, 11)), 'review-policy-date')
if __name__ == '__main__': unittest.main()دستور اجرا، نتیجهٔ مورد انتظار و محدودیت این فایل در بخش اجرای مقاله توضیح داده شده است.
اجرای موجودی و آزمون تصمیمهای مرزی
برای انتشار واقعی، مسیر دریافت و کنترل چکیدهٔ بسته را از راهنمای رسمی همان محیط بگیرید و وابستگیها را با روش مورد حمایت فروشنده تغییر دهید. پیش از تغییر، معیار بازگشت و امکان اجرای نسخهٔ قبلی را مشخص کنید. اطلاعات تقویم میتواند تغییر کند؛ بعد از موعد بازبینی، دادهٔ سیاست را دوباره با منبع رسمی تطبیق دهید. هدف، تصمیم شفاف بر اساس محیط واقعی است، نه ارتقای خودکار تنها به دلیل بزرگتر بودن شمارهٔ نسخه.
چکلیست اجرای عملی
- نسخهٔ کتابخانهٔ واقعی هر سرویس ثبت شود.
- سیاست پس از مهلت بازبینی خودکار پذیرفته نشود.
- اطلاعیهٔ بستهٔ توزیع جدا بررسی شود.
- اتصالهای واقعی پس از تغییر آزمون شوند.
منابع
تدوین و راهنمای عملی: دانشنامه لیان.




