Sizlere bu seride, komut satırı uygulamaları yazarken uyguladığım yöntemlerden ve "best practice" olarak geçen kavramlardan bahsedeceğim. Bu yazdıklarım elbette olmazsa olmaz değil, fakat size daha iyi komut satırı uygulamaları yazmanıza yardımcı olacağına eminim.
Çıktıları loglayın, yoksa kanıtlayamazsınız!
Loglama herhangi bir uygulamanın temel yapı taşıdır. Komut satırı uygulamaları için, yapılan işin ve sonucunun detaylarıyla loglanması bana kalırsa hayatidir.
Ben bunun için genel olarak çok basit bir yöntem kullanıyorum.
/var/www/artisan some:command > $HOME/logs/some-command/`date +%Y-%m-%d-%H-%M-%S`.log 2>&1
Çalışan komut satırı uygulaması ile ilgili çıktıyı, onunla ilgili olan bir klasör içerisine çalışma saatiyle yazdırıyorum. Bunu crontab içerisine de yazabilirsiniz. Böylece basitçe bir ls
komutu yardımıyla, o uygulamanın çalıştığı zamanları hızlıca görebilirsiniz.
Peki bu çıktı neler içermeli? Tabi ki uygulamanın ne yaptığına bağlı olarak değişir bu. Uygulamanın ne yapacağı, çalıştırmanın neleri etkileyeceği ve çalıştıktan sonra nelerin etkinlendiğini yazmak en temel konulardır. Ama açıkçası aklınıza ne gelirse yazabilirsiniz. Yazmaktan da çekinmeyin.
Örnek bir uygulama
Biraz daha realize etmeye çalışalım. Varsayalım ki kullanıcıların güncel üyelik(subscription) durumlarını kontrol eden ve eğer para ödemiyorlarsa onları pasifleştiren bir uygulama yazdınız.
Evet bu işi normalde webhook ile yapmamız daha mantıklı. Özellikle Stripe çok güzel webhook gönderimi yapıyor ve birkaç kez deniyor. Ama webhooklara her zaman güvenebilir miyiz? Bazen uygulamamızda bir problem olabilir, uygulama kapalı kalabilir. Ya da yazdığımız bir logic doğru sonuç vermiyor olabilir. Her zaman ikinci bir kontrol yapmakta fayda var.
<?php
$users = User::where('is_active', true)->get(); // TODO: use cursors instead of getting whole data. This will be fixed in the next chapters!
$this->output->writeln('There are '.$users->count().' users to be checked for subscription control.');
foreach ($users as $user) {
if (!$this->stripeService->isUserActive($user)) {
$this->userService->disableUser($user);
$this->output->writeln('User have been disabled: user_id_'.$user->id);
}
}
$this->output->writeln('Done');
return 0;
Yukarıdaki basit komut satırı uygulamasının çıktısı aşağıdaki gibi olacak:
There are 1989 users to be checked for subscription control.
User have been disabled: user_id_100
User have been disabled: user_id_157
Done.
Gördüğünüz gibi uygulama ne yapacağının bilgisini veriyor. Daha sonra 2 kullanıcıya işlem yaptığını bildiriyor. Ve en sonunda basitçe "Done." yazarak çalışmanın sonlandığını bildiriyor.
Bu çıktı dosyasını artık isterseniz bash kullanarak inceleyebilirsiniz, isterseniz basit scriptler yazabilir ya da ELK, Datadog, Coralogix, Graylog, Papertrail gibi sistemlere kolayca atabilirsiniz.
Çıktılar üzerinde bilgiyi bulun
Çoğunlukla, bir log yönetim sistemi kullanmayacağınızı tahmin ediyorum. Genelde bu durum atlanır. Bu durumda da loglarda bir arama yapmanız gerekiyor olabilir. Bu iş için grep
kullanabilirsiniz. (Daha birçok yöntem var aynı işi yapan.)
grep -Ril -e 'user_id_100' $HOME/logs/some-command/
Bu basit komut sonrasında kullanıcının pasifleştirildiğini göreceksiniz. Eğer bunu loglamasaydınız, neden pasifleştirildiğini anlamayabilirdiniz.
Formatlı yazdırma
Dosyaya çıktı verdiğimizde, datayı search edilebilir vermek oldukça önemli. Ben örneğimde user_id_XXXX
olarak verdim. Tüm komut satırı uygulamalarından aynı formatta verdiğimde, "user_id_XXXX
ile ilgili komut satırında yapılan işlemler" listesine kolayca ulaşabileceğim.
Laravel’de cronjob çıktısını yazdırma
Laravel’e özel bir başlık açıyorum. Sıklıkla Scheduler özelliğini kullanıyorum. İşleri bence oldukça kolaylaştıran ve takip edilebilmesini sağlayan bir yöntem.
Laravel bu noktada bize bir kolaylık sağlıyor ve çıktıları dosya sistemine yazabilmemize olanak tanıyor.
$schedule->command('emails:send')
->daily()
->appendOutputTo(storage_path('cronjob-logs/emails_send_'.date('YmdHis'));
Günlük çalıştırdığım ve belirlenen emailleri gönderen bir uygulamamız olsun. Bunun çıktısını storage klasörü altına yazabiliriz.
Sonuç
Loglamak bir uygulamadaki en kritik konu bence. Çıktıları kaydetmek oldukça basit. Sizin için neyin değerli olduğuna karar vermeniz ve kendiniz için bir log yapısı kurmanız gerekiyor. Bir kez log yapısı kurduktan sonra, bir daha birşey yapmanıza gerek kalmıyor. Tabi debug gerekmedikçe :) Umarım gerekmez, ama her zaman hazırlıklı olmakta fayda var.