اتخطّى للمحتوى

المرحلة 05 · الأداء والتشغيلدرس 29 من 3415 دقيقة قراءةآخر تحديث:

Lesson 29 / 34

Cron & CLIالمهام والأوامر.

المهام المجدولة اللي بتشغّل نص Magento في الخلفية، والأوامر اللي بتستخدمها كل يوم. إزاي يشتغلوا، إزاي تعمل بتاعك، وإزاي تشخّص لما يقفوا.

● يومي المجموعات أوامر مخصّصة التشخيص

الـ cron في Magento 2 بيشتغل على طبقتين: cron النظام بينده bin/magento cron:run كل دقيقة، وجدولة Magento بتقرر أي مهمة حان وقتها حسب crontab.xml وتسجّلها في جدول cron_schedule بحالات pending و running و success و missed و error. المهام متجمّعة في مجموعات زي default و index و consumers. والـ CLI أوامر Symfony Console بتسجّلها في di.xml.

// ليه الـ cron أخطر مما تتخيّل الـ cron بيقع بصمت. مفيش صفحة بتطلّع خطأ، ومفيش عميل بيشتكي فوراً. بس من غيره: الفهارس مابتتحدّثش، الإيميلات مابتتبعتش، الـ consumers مابتشتغلش، والأسعار والمخزون بيفضلوا قديمين. ولما حد يلاحظ، بيبقى عدى أسبوع والمشاكل متراكمة. ده أول حاجة تشيّك عليها في أي مشروع تستلمه.
◆ Part 1 — الـ Cron
01

إزاي الـ Cron بيشتغل

فيه طبقتين بيتخلطوا، والفرق بينهم أساس التشخيص.

cron النظام
cron:run
جدول الجدولة
المهام
layer
cron النظام (Linux)
بينده bin/magento cron:run كل دقيقة.
مسؤوليتهمجرد نداء متكرّر. لو ده مش موجود، مفيش أي حاجة بتشتغل.
جدولة Magento
بتقرر أي مهمة حان وقتها وتشغّلها.
مسؤوليتهالجدولة الفعلية حسب crontab.xml.
تشبيه زي منبّه بيرن كل دقيقة، ومعاك أجندة مواعيد. المنبّه (cron النظام) بيصحّيك، وإنت بتبص في الأجندة (جدولة Magento) وتشوف فيه حاجة دلوقتي ولا لأ. لو المنبّه واقف، الأجندة مالهاش لازمة مهما كانت مظبوطة.
إعداد cron النظامbash
# الطريقة الرسمية — Magento بيكتبه بنفسه
bin/magento cron:install

# شوف اللي اتكتب
crontab -l

# الشكل المتوقّع تقريباً:
# * * * * * /usr/bin/php /var/www/bin/magento cron:run
!
الـ crontab لازم يكون لمستخدم الـ web server (عادة www-data)، مش root. لو اتعمل بـ root، الملفات اللي المهام بتكتبها هتبقى مملوكة لـ root — والـ web server مش هيقدر يكتب عليها بعدين. ده سبب متكرر لأخطاء صلاحيات غامضة.
• • •
02

المجموعات والإعدادات

المهام متجمّعة، وكل مجموعة بإعداداتها.

group
default
معظم المهام — الإيميلات، التنظيف، إعادة الفهرسة.
ملاحظةالأكبر والأكتر ازدحاماً.
index
مهام الفهرسة.
ملاحظةمنفصلة عشان الفهرسة التقيلة ماتعطّلش الباقي.
consumers
تشغيل الـ queue consumers.
ملاحظةلو بتستخدم الطوابير (درس RabbitMQ).
إعدادات كل مجموعة

من Stores → Configuration → Advanced → System → Cron.

setting
Generate Schedules Every
كل قد إيه يتولّد جدول المواعيد الجاية (بالدقايق).
الافتراضي15 دقيقة.
Schedule Ahead For
بيولّد مواعيد لقد إيه في المستقبل.
الافتراضي20 دقيقة.
Missed if Not Run Within
بعد قد إيه المهمة تتعلّم missed.
مهملو قصيرة والمهام تقيلة، هتلاقي missed كتير من غير مشكلة حقيقية.
History Cleanup Every
كل قد إيه ينضّف السجلات القديمة.
مهممن غيره cron_schedule بيكبر بلا حدود.
Use Separate Process
هل المجموعة تشتغل في عملية مستقلة.
امتىفعّلها للمجموعات التقيلة عشان ماتعطّلش غيرها.
i
الـ Use Separate Process مفيد جداً. من غيره، مهمة تقيلة في مجموعة بتأخّر كل المهام في نفس المجموعة. مع التفعيل، كل مجموعة بتشتغل مستقلة — فالفهرسة مابتعطّلش الإيميلات.
• • •
03

جدول الجدولة

فهم الجدول ده = فهم التشخيص.

جدول cron_schedule

كل مهمة مجدولة بتتسجّل فيه كصف بحالة وأوقات.

status
pending
مجدولة ولسه ماجاش وقتها.
طبيعيالحالة الافتراضية للمهام الجاية.
running
شغّالة دلوقتي.
حذرصف running من ساعات = عملية عالقة.
success
خلصت بنجاح.
طبيعيده اللي المفروض تشوفه أغلب الوقت.
missed
جه وقتها ومااشتغلتش في المدة المسموحة.
مؤشرعدد قليل طبيعي. كتير = الـ cron بطيء أو واقف.
error
اشتغلت ورمت استثناء.
مؤشرشوف عمود messages — فيه سبب الخطأ.
استعلامات التشخيصsql
-- توزيع الحالات في آخر ساعة
SELECT status, COUNT(*)
FROM cron_schedule
WHERE scheduled_at > NOW() - INTERVAL 1 HOUR
GROUP BY status;

-- آخر المهام الناجحة — هل الـ cron حي؟
SELECT job_code, executed_at
FROM cron_schedule
WHERE status = 'success'
ORDER BY executed_at DESC LIMIT 10;

-- الأخطاء بأسبابها
SELECT job_code, messages, scheduled_at
FROM cron_schedule
WHERE status = 'error'
ORDER BY scheduled_at DESC LIMIT 20;

-- مهام عالقة في running
SELECT job_code, executed_at
FROM cron_schedule
WHERE status = 'running'
  AND executed_at < NOW() - INTERVAL 1 HOUR;
i
الاستعلام التاني هو أسرع فحص للصحة. لو آخر success من ساعتين، الـ cron واقف — وكل حاجة معتمدة عليه واقفة معاه. خليه أول حاجة تعملها في أي مشروع جديد.
!
المهام العالقة في running بتمنع نفسها من الاشتغال تاني. Magento بيشوف إن فيه نسخة شغّالة فمابيشغّلش تانية. لو العملية ماتت من غير ما تحدّث الحالة، المهمة دي هتفضل واقفة للأبد لحد ما تصلّح الصف يدوياً.
• • •
04

عمل مهمة مخصّصة

من التعريف للتشغيل.

etc/crontab.xmlxml
<?xml version="1.0"?>
<config>
  <group id="default">

    <!-- جدولة ثابتة -->
    <job name="vendor_cleanup_old_data"
      instance="Vendor\Module\Cron\CleanupOldData"
      method="execute">
      <!-- كل يوم 3 صباحاً -->
      <schedule>0 3 * * *</schedule>
    </job>

    <!-- جدولة من الإعدادات — الأفضل -->
    <job name="vendor_sync_erp"
      instance="Vendor\Module\Cron\SyncErp"
      method="execute">
      <config_path>vendor/sync/schedule</config_path>
    </job>

  </group>
</config>
الفرق بين الطريقتين

schedule

التوقيت ثابت في الكود. تغييره يحتاج نشر.

config_path

التوقيت من الإعدادات. الفريق يغيّره من الأدمن.

i
استخدم config_path لأي مهمة تخص التشغيل — مزامنة، تقارير، تنظيف. فريق التشغيل هيحتاج يغيّر التوقيت في وقت ما، ومن غير الإعداد ده هيحتاج نشر كامل عشان تغيير رقم.
قراءة تعبير الجدولة
* * * * *
1minute0–59
2hour0–23
3day1–31
4month1–12
5weekday0–6 (0 = الأحد)
أمثلة شائعةtext
*/15 * * * *    # كل 15 دقيقة
0 * * * *       # كل ساعة في الدقيقة صفر
0 3 * * *       # كل يوم 3 صباحاً
0 3 * * 1       # كل إثنين 3 صباحاً
0 0 1 * *       # أول كل شهر
*/5 9-17 * * 1-5 # كل 5 دقايق، أيام العمل بس
Cron/SyncErp.phpphp
namespace Vendor\Module\Cron;

use Psr\Log\LoggerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;

class SyncErp
{
    private const ENABLED_PATH = 'vendor/sync/enabled';

    public function __construct(
        private readonly ScopeConfigInterface $config,
        private readonly SyncService $service,
        private readonly LoggerInterface $logger
    ) {}

    public function execute(): void
    {
        // 1. مفتاح تعطيل — مهم جداً
        if (!$this->config->isSetFlag(self::ENABLED_PATH)) {
            return;
        }

        $start = microtime(true);

        try {
            $count = $this->service->sync();

            // 2. سجّل النجاح بأرقام مفيدة
            $this->logger->info('ERP sync done', [
                'records'  => $count,
                'duration' => round(microtime(true) - $start, 2),
            ]);

        } catch (\Exception $e) {
            // 3. سجّل وارمي — عشان تتعلّم error
            $this->logger->error('ERP sync failed', [
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }
}
التلات قرارات في الكود ده
  • مفتاح التعطيل — لو المهمة سبّبت مشكلة في production، فريق التشغيل يقدر يوقفها من الأدمن فوراً من غير نشر.
  • تسجيل بأرقام — عدد السجلات والمدة. من غيرهم مش هتعرف المهمة بتتقل ولا لأ إلا لما تقع.
  • الرمي بعد التسجيل — عشان الحالة تتعلّم error وتبان في الجدول.
!
النقطة التالتة عكس القاعدة في الـ observers. في الـ observer بتبلع الاستثناء عشان ماتوقّعش العملية الأصلية. في الـ cron بترميه عشان الفشل يتسجّل ويبان — المهمة مالهاش عملية أصلية تعطّلها.
• • •
05

تشخيص الـ Cron

لما حاجة تقف والسبب مش واضح.

  • الـ crontab موجود؟crontab -l بمستخدم الـ web server.
  • الـ cron بيشتغل فعلاً؟ — آخر success في الجدول.
  • المهمة بتتجدول؟ — دوّر على job_code بتاعها.
  • بتقع بخطأ؟ — شوف عمود messages.
  • عالقة في running؟ — عملية ماتت من غير تحديث.
  • الجدول متضخّم؟ — بيبطّئ كل حاجة.
أوامر مفيدةbash
# شغّل يدوياً وشوف المخرجات
bin/magento cron:run

# مجموعة محددة
bin/magento cron:run --group=index

# هل فيه عمليات cron شغّالة؟
ps aux | grep cron:run

# أخطاء الـ cron في السجلات
grep -i cron var/log/system.log | tail -30
إصلاح المهام العالقة
تنظيف — بحذرsql
-- شوف الأول قبل ما تعدّل
SELECT * FROM cron_schedule
WHERE status = 'running'
  AND executed_at < NOW() - INTERVAL 2 HOUR;

-- بعد التأكد إن مفيش عملية شغّالة فعلاً
UPDATE cron_schedule
SET status = 'error',
    messages = 'Manually cleared - stuck'
WHERE status = 'running'
  AND executed_at < NOW() - INTERVAL 2 HOUR;
!
تأكد بـ ps aux إن مفيش عملية شغّالة فعلاً قبل ما تعدّل الحالة. لو المهمة لسه شغّالة وغيّرت حالتها، Magento ممكن يشغّل نسخة تانية — ولو المهمة بتكتب بيانات، هتبقى عندك نسختين بيكتبوا في نفس الوقت.
الجدول المتضخّم

لو التنظيف مش شغّال، cron_schedule بيوصل لملايين الصفوف. النتيجة: كل نداء للـ cron بيبطّئ، ومع الوقت المهام بتبدأ تتعلّم missed من غير سبب حقيقي.

فحص الحجمsql
SELECT COUNT(*) AS total,
       MIN(scheduled_at) AS oldest
FROM cron_schedule;

-- لو الأقدم من شهور، التنظيف مش شغّال
• • •
◆ Part 2 — الـ CLI
06

الأوامر الأساسية

اللي بتستخدمها كل يوم.

الكاش والفهارسbash
bin/magento cache:status
bin/magento cache:clean config layout block_html
bin/magento cache:flush

bin/magento indexer:status
bin/magento indexer:reindex
bin/magento indexer:set-mode schedule
الموديولات والتحديثbash
bin/magento module:status
bin/magento module:enable Vendor_Module
bin/magento module:disable Vendor_Module

bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f ar_SA en_US
الإعداداتbash
# اقرا إعداد
bin/magento config:show web/secure/base_url

# غيّر إعداد
bin/magento config:set web/secure/use_in_frontend 1

# إعداد حسّاس — بيتشفّر
bin/magento config:set:sensitive payment/gateway/key VALUE
وضع التشغيل والصيانةbash
bin/magento deploy:mode:show
bin/magento deploy:mode:set production

bin/magento maintenance:enable
bin/magento maintenance:enable --ip=1.2.3.4
bin/magento maintenance:disable
الطوابير والأدمنbash
bin/magento queue:consumers:list
bin/magento queue:consumers:start NAME --max-messages=100

bin/magento admin:user:create
bin/magento admin:user:unlock USERNAME
bin/magento info:adminuri
!
الـ maintenance:enable --ip بيحفظ حياتك. بيحط الموقع في وضع الصيانة للكل ماعدا الـ IP بتاعك — فتقدر تختبر قبل ما تفتح للعملاء. من غيرها إما الموقع مقفول عليك كمان أو مفتوح للكل وهو لسه مش جاهز.
i
bin/magento list بيعرض كل الأوامر المتاحة، وbin/magento help COMMAND بيشرح أمر معيّن بخياراته. مفيد لما تنسى صيغة أمر.
• • •
07

عمل أمر مخصّص

أبسط شكل، مشروح سطر سطر.

etc/di.xml — التسجيلxml
<type name="Magento\Framework\Console\CommandList">
  <arguments>
    <argument name="commands" xsi:type="array">
      <item name="vendorSyncProducts" xsi:type="object">
        Vendor\Module\Console\Command\SyncProducts
      </item>
    </argument>
  </arguments>
</type>
Console/Command/SyncProducts.phpphp
namespace Vendor\Module\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class SyncProducts extends Command
{
    public function __construct(
        private readonly SyncService $service,
        $name = null
    ) {
        parent::__construct($name);
    }

    // اسم الأمر ووصفه
    protected function configure(): void
    {
        $this->setName('vendor:sync:products');
        $this->setDescription('Sync products from ERP');

        parent::configure();
    }

    // المنطق
    protected function execute(
        InputInterface $input,
        OutputInterface $output
    ): int {
        try {
            $count = $this->service->sync();

            $output->writeln(
                "<info>Synced {$count} products</info>"
            );

            // 0 = نجاح
            return Command::SUCCESS;

        } catch (\Exception $e) {
            $output->writeln(
                "<error>{$e->getMessage()}</error>"
            );

            // غير صفر = فشل
            return Command::FAILURE;
        }
    }
}
النقاط المهمة
  • اسم الأمر — بصيغة vendor:group:action عشان ينتظم مع الباقي.
  • القيمة الراجعة0 نجاح، 1 فشل. مهمة جداً في السكريبتات والأتمتة.
  • وسوم التلوين<info> أخضر، <error> أحمر، <comment> أصفر.
!
القيمة الراجعة بتتنسي كتير. لو أمرك بيرجّع 0 دايماً حتى لو فشل، أي سكريبت نشر أو أتمتة هيفتكر إنه نجح ويكمّل. في الـ CI/CD ده معناه نشر بيكمّل على خطوة فشلت.
التفعيلbash
bin/magento setup:upgrade
bin/magento cache:clean

# شوفه في القائمة
bin/magento list | grep vendor

# شغّله
bin/magento vendor:sync:products
• • •
08

أمر متقدّم

مدخلات، خيارات، وشريط تقدّم.

مدخلات وخياراتphp
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

protected function configure(): void
{
    $this->setName('vendor:sync:products');

    // مُدخل إجباري
    $this->addArgument(
        'source',
        InputArgument::REQUIRED,
        'Source system code'
    );

    // خيار بقيمة
    $this->addOption(
        'limit', 'l',
        InputOption::VALUE_OPTIONAL,
        'Max records',
        100  // القيمة الافتراضية
    );

    // خيار بدون قيمة — علم
    $this->addOption(
        'dry-run', null,
        InputOption::VALUE_NONE,
        'Preview without saving'
    );

    parent::configure();
}
القراءة والتنفيذphp
protected function execute(
    InputInterface $input,
    OutputInterface $output
): int {
    $source = $input->getArgument('source');
    $limit  = (int) $input->getOption('limit');
    $dryRun = (bool) $input->getOption('dry-run');

    if ($dryRun) {
        $output->writeln(
            '<comment>Dry run — nothing saved</comment>'
        );
    }

    $records = $this->service->fetch($source, $limit);

    // شريط تقدّم — مفيد للعمليات الطويلة
    $progress = new ProgressBar($output, count($records));
    $progress->start();

    foreach ($records as $record) {
        if (!$dryRun) {
            $this->service->save($record);
        }
        $progress->advance();
    }

    $progress->finish();
    $output->writeln('');

    return Command::SUCCESS;
}
الاستخدامbash
bin/magento vendor:sync:products erp
bin/magento vendor:sync:products erp --limit=500
bin/magento vendor:sync:products erp --dry-run
i
الـ --dry-run عادة ممتازة في أي أمر بيعدّل بيانات. بيخلّي الفريق يشوف إيه اللي هيحصل قبل ما يحصل — وده بيمنع أخطاء مكلّفة على production، خصوصاً في أوامر التحديث الجماعي.
!
لو الأمر بيعالج بيانات كتير، خد بالك من الذاكرة. حمّل على دفعات بدل ما تجيب كل حاجة مرة واحدة. أمر بيلف على 100 ألف منتج بيقع بـ memory exhausted لو حمّلهم كلهم.
• • •
◆ Part 3 — الخلاصة
09

الفخاخ الشائعة

اقرا دي حتى لو مش هتقرا حاجة تانية.

  • مفيش crontab أصلاً — كل حاجة في الخلفية واقفة بصمت. الفخ الأول.
  • crontab بمستخدم root — مشاكل صلاحيات غامضة في الملفات.
  • مهام عالقة في running — بتمنع نفسها من الاشتغال للأبد.
  • جدول cron_schedule متضخّم — بيبطّئ كل نداء للـ cron.
  • بلع الاستثناء في مهمة cron — الفشل مابيبانش في الجدول.
  • مفيش مفتاح تعطيل — مهمة سبّبت مشكلة ومحتاج نشر عشان توقفها.
  • جدولة ثابتة في الكود — تغيير التوقيت محتاج نشر.
  • أمر بيرجّع 0 دايماً — سكريبتات النشر بتفتكر إنه نجح.
  • تحميل كل البيانات في أمر — نفاد الذاكرة.
  • تعديل حالة running من غير فحص — نسختين بيشتغلوا مع بعض.
i
لو حاجة في الخلفية مش شغّالة، اسأل بالترتيب: الـ crontab موجود؟آخر success امتى؟المهمة بتتجدول؟فيه error أو عالقة في running؟
• • •
10

أسئلة الإنترفيو

الأسئلة المتكررة.

Q1إزاي الـ cron بيشتغل في Magento؟
الإجابة: طبقتين. cron النظام بينده bin/magento cron:run كل دقيقة، وجدولة Magento بتقرر أي مهمة حان وقتها حسب crontab.xml وتسجّلها في cron_schedule. لو طبقة النظام مش موجودة، مفيش أي حاجة بتشتغل مهما كانت الجدولة مظبوطة.
Q2مهمة cron مش بتشتغل — تشخّص إزاي؟
الإجابة: بالترتيب: أتأكد إن الـ crontab موجود بمستخدم الـ web server، بعدين أشوف آخر success في cron_schedule عشان أعرف الـ cron حي ولا لأ، بعدين أدوّر على job_code بتاع المهمة وأشوف حالتها وعمود messages. وأشيّك لو عالقة في running — دي بتمنع نفسها من الاشتغال تاني.
Q3إيه حالات جدول الـ cron؟
الإجابة: pending مجدولة، running شغّالة، success خلصت، missed فات وقتها، error وقعت. الـ missed بكثرة معناه الـ cron بطيء أو واقف، وrunning من ساعات معناه عملية ماتت من غير ما تحدّث حالتها.
Q4إزاي تعمل أمر CLI مخصّص؟
الإجابة: كلاس بيورّث من Symfony\Console\Command، بحدد الاسم والوصف في configure() والمنطق في execute()، وأسجّله في di.xml تحت CommandList. ومهم أرجّع 0 للنجاح وغير صفر للفشل عشان السكريبتات تقدر تتصرّف صح.
Q5ليه تستخدم config_path بدل schedule؟
الإجابة: عشان التوقيت يتغيّر من الأدمن بدل ما يحتاج نشر. أي مهمة تشغيلية — مزامنة، تقارير، تنظيف — فريق التشغيل هيحتاج يعدّل توقيتها في وقت ما، والـ config_path بيخلّي ده ممكن من غير مطوّر.
Q6ليه ترمي الاستثناء في cron وتبلعه في observer؟
الإجابة: الـ observer بيشتغل جوّه عملية أصلية — لو رمى استثناء هيوقّعها، فبسجّل وأبلع. الـ cron مالوش عملية أصلية يعطّلها، والرمي هو اللي بيخلّي الحالة تتعلّم error وتبان في الجدول. لو بلعته، الفشل هيبقى صامت تماماً.

Cron & CLI ✓

دلوقتي فاهم الطبقتين في الـ cron، جدول الجدولة وحالاته، إزاي تعمل مهمة وأمر مخصّصين، وإزاي تشخّص لما حاجة تقف.

الخلاصة: الـ cron بيقع بصمت فاعمله فحص دوري، ارمي الاستثناء في المهام عشان الفشل يبان، وأي أمر لازم يرجّع كود خروج صحيح.

// magento 2 · cron · cli · commands

خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.

كاتب الدرس

Abdulrahman Masoud

عندك سؤال على الدرس أو محتاج مساعدة في مشروع Magento؟ كلّمني.

أسئلة شائعة

إزاي الـ cron بيشتغل في Magento 2؟

طبقتين. cron النظام في Linux بينده bin/magento cron:run كل دقيقة، وجدولة Magento جوّه الأمر ده بتقرر أي مهمة حان وقتها حسب ملفات crontab.xml وتسجّلها في جدول cron_schedule وتشغّلها. لو الـ crontab مش موجود مفيش أي حاجة بتشتغل في الخلفية مهما كانت الجدولة مظبوطة.

الـ cron في Magento مش بيشتغل، أشخّص إزاي؟

بالترتيب: اتأكد إن الـ crontab موجود بمستخدم الـ web server بـ crontab -l، وبعدين شوف آخر صف بحالة success في cron_schedule عشان تعرف الـ cron حي ولا لأ، وبعدين دوّر على الـ job_code بتاع المهمة وشوف حالتها وعمود messages. لو لقيتها running من ساعات، فده غالبًا process ماتت من غير ما تحدّث الحالة.

إيه حالات جدول cron_schedule في Magento 2؟

خمس حالات: pending مجدولة ولسه، running شغّالة دلوقتي، success خلصت، missed فات وقتها ومااشتغلتش في المدة المسموحة، و error وقعت وسبب الخطأ في عمود messages. الـ missed بكثرة معناه الـ cron بطيء أو واقف، وصف running من ساعات معناه مهمة عالقة بتمنع نفسها من الاشتغال تاني.

إزاي أعمل مهمة cron مخصّصة في Magento 2؟

عرّفها في etc/crontab.xml جوّه &lt;group id="default"&gt; بـ &lt;job name instance method&gt;، والتوقيت إما &lt;schedule&gt; ثابت بصيغة cron أو &lt;config_path&gt; عشان يتغيّر من الأدمن. الكلاس عادي فيه method execute. ضيف مفتاح تعطيل من الإعدادات، وسجّل النتيجة بالأرقام، وارمي الـ exception عشان الفشل يتعلّم error في الجدول.

إزاي أعمل أمر CLI مخصّص في Magento 2؟

كلاس بيورّث من Symfony\Component\Console\Command\Command، بتحدد الاسم والوصف في configure() والمنطق في execute()، وبتسجّله في etc/di.xml كـ item جوّه argument commands بتاع Magento\Framework\Console\CommandListInterface. بعد setup:upgrade و cache:clean بيظهر في bin/magento list. ارجّع 0 للنجاح وغير صفر للفشل عشان سكريبتات النشر تتصرّف صح.

إزاي أصلّح مهمة cron عالقة في حالة running؟

الأول اتأكد بـ ps aux | grep cron:run إن مفيش process شغّالة فعلًا. بعدها حدّث الصفوف القديمة في cron_schedule اللي حالتها running من أكتر من ساعتين لحالة error برسالة توضّح إنك مسحتها يدويًا. لو غيّرت الحالة والمهمة لسه شغّالة، Magento هيشغّل نسخة تانية وهيبقى عندك اتنين بيكتبوا في نفس الوقت.

إيه الفرق بين schedule و config_path في crontab.xml؟

&lt;schedule&gt; بيثبّت التوقيت في الكود، فأي تغيير محتاج نشر. &lt;config_path&gt; بيقرا التوقيت من مسار إعداد، فتقدر تعرضه في system.xml وفريق التشغيل يغيّره من الأدمن. استخدم config_path لأي مهمة تشغيلية زي المزامنة والتقارير والتنظيف، لأن توقيتها هيتغيّر في وقت ما.