Ansible : Hedef Sistemlerde Shell Komutlarını Çalıştırma

Ansible’ın kabuk modülü, playbooklarınız ile yönetilen sistemlerinizin komut satırı arayüzü (CLI) arasında bir köprü görevi görür. Uzak hedeflerde kabuk komutları yürütmenize olanak tanıyarak bir dizi farklı sistem yönetimi, konfigürasyon yönetimi ve otomasyon görevini gerçekleştirmeyi kolaylaştırır.

 

Kabuk Modülü nedir?

Kabuk modülü özünde, ister dosya izinlerini kontrol etmek gibi basit görevler ister özel komut dosyaları çalıştırmak gibi karmaşık işlemler için olsun, uzak  bilgisayarlardaki bir kabuk ortamında komutları çalıştırmak üzere tasarlanmış bir Ansible yapı taşıdır.

Kabuk modülü, hedef makinelerinizle güvenli bir bağlantı kurmak için Ansible’ın bağlantı eklentilerini kullanır. Bağlandıktan sonra bir kabuk oturumu oluşturur (genellikle Unix benzeri sistemlerde /bin/sh) ve bu kabuk içinde sağladığınız komutu yürütür. Modül daha sonra komutun çıkışını (stdout ve stderr) ve dönüş kodunu yakalar ve bu bilgileri playbook’unuzda daha fazla işlenmek üzere kullanılabilir hale getirir.

Ansible kabuk modülü parametreleri

Kabuk modülünün bir dizi farklı parametresi vardır. En sık kullanılanlardan bazıları şunlardır:

  • cmd (or free form): Modülün çekirdeği, çalıştırmak istediğiniz komutu belirttiğiniz yerdir.
  • creates: Bir kez işlemin sağlanmasına yardımcı olur. Belirtilen dosya varsa, komut yürütülmez.
  • chdir: Komutu çalıştırmadan önce çalışma dizinini değiştirmenizi sağlar.
  • executable: Belirli bir kabuk yorumlayıcısına ihtiyacınız varsa (/bin/bash gibi), bu parametreyi kullanın.
  • removes: creates’in tersi davranır. Belirtilen dosya yoksa komut çalışmaz.

Bunlar mevcut parametrelerden sadece birkaçıdır: Ansible’ın belgeleri kapsamlı bir liste sağlar.

Kabuk modülünü kullanma: Pratik bir örnek

Bu örnekte, uzak bir ana bilgisayardaki bir dizinin yedeğini oluşturacağız ve /opt/myapp içeriğini ona kopyalayacağız ve ardından yedekleme dizininin içeriğini listeleyerek yedeklemenin tamamlandığını doğrulayacağız. Yedekleme başarılı olursa, bunu onaylayan bir mesaj görüntülenecektir.

  ---
- name: Create directory backup using shell module
  hosts: all
  become: true
  tasks:
    - name: Create backup directory
      ansible.builtin.shell: |
      mkdir -p /var/backups/myapp
      
    - name: Copy files to backup directory
      ansible.builtin.shell: |
        cp -r /opt/myapp /var/backups/myapp

    - name: Verify backup completion
      ansible.builtin.shell: |
        ls /var/backups/myapp
      register: backup_result

    - name: Display backup status
      debug:
        msg: "Backup completed successfully: {{ backup_result.stdout_lines }}"
      when: backup_result.rc == 0

Birden Çok Kabuk Komutu Çalıştırma

Kabuk modülü tek bir komut için tasarlanmış olsa da, çok satırlı bir dize veya kabuk işleçleriyle tek bir dize kullanarak birden çok komutu zincirleyebilir veya bir kabuk komut dosyası oluşturabilir ve bunu kabuk modülüyle çalıştırabilirsiniz.

---
- name: Run multiple commands
  hosts: all
  become: true
  tasks:
    - name: Execute multiple commands using shell module
      ansible.builtin.shell: |
        echo "Starting setup..."
        mkdir -p /opt/myapp
        touch /opt/myapp/config.yaml
        echo "Setup complete."

Shell Modülü ile Changed_when ve Failed_when Kullanımı

Kabuk modülü değiştirilen durumu döndürmez. Bir komutun ne zaman başarısız olduğunu veya bir komut dosyasının sistemdeki bir şeyi değiştirdiğini gerçekten tanımlamak için failed_when changed_whenand deyimlerini kullanabilirsiniz.

Talimat changed_when, bir görevin hedefte gerçekten ne zaman değişiklik yapacağını tanımlamanıza olanak tanır.

- name: Install dependencies via Composer.
  ansible.builtin.shell: "/usr/local/bin/composer global require phpunit/phpunit --prefer-dist"
  register: composer
  changed_when: "'Nothing to install or update' not in composer.stdout"

Eğer php modülleri hedefte zaten mevcutsa, composer komutu hiçbir şey yapmaz ve sadece mesajı döndürür.

Bazı hataların kabul edilebilir olduğu durumlar olabilir. Bu tür bir durumda talimatı failed_when kullanacağız.

- name:
  ansible.builtin.shell: "ls | grep wp-config.php"
  register: thecommand
  failed_when: thecommand.rc not in [0, 1]

Ayrıca, bir yükleme aracının kaynak yetersizliği nedeniyle çökmesini önlemek için bir playbook başlatırken de kullanılabilir.

- name: Making sure the /tmp has more than 2gb
  ansible.builtin.shell: "df -h /tmp|grep -v Filesystem|awk '{print $4}'|cut -d G -f1"
  register: tmpspace
  failed_when: "tmpspace.stdout|float < 2"

Kabuk ve komut modülü

Ansible’da aynı amaca hizmet eden bir komut modülü vardır; hedefler üzerinde komutları yürütmek.
Bu iki modülün amacı aynı olsa bile farklılıklar vardır:

  • Ansible kabuk modülü, komutları doğrudan hedef bilgisayarların kabuğu aracılığıyla yürütür. Varsayılan kabuk modülü, komutları yürütmek için varsayılan olarak sh kullanır (executable seçeneği aracılığıyla başka kabuklar tanımlamak mümkündür). Modül komutuyla, komutlar kabuk aracılığıyla yürütülmez.
  • Modül komutu <, >, &, ;… gibi ortam değişkenlerini, boruları ve operatörleri desteklemez.

Bu nedenle, kullanıcının kabuk değişkenlerinden etkilenmediği için modül komutlarını kullanmak daha güvenlidir. Öte yandan, operatörler kullanılamadığı için, playbooklardaki değerleri Jinja filtreleri aracılığıyla işlemeniz gerekir.

Kabuk modülü neden önerilmez?

Kabuk modülü güçlü olsa ve size komut dosyası yazma esnekliği sağlasa da, genellikle kullanımı önerilmez ve özel modüller kullanmak daha iyi bir uygulama olarak kabul edilir. Kabuk modülünün kullanımının önerilmemesinin birkaç nedeni vardır:

  • İdempotens: İdempotensi (aynı playbooku yan etkilere neden olmadan birden fazla kez çalıştırmak) kabuk komut dosyalarını kullanarak sağlamak zorlu bir iştir.
  • Okunabilirlik ve Bakım: Shell betikleri, özel Ansible modüllerinin kullanılmasına kıyasla okunması, anlaşılması ve bakımı daha zor olabilir ve nelerin değiştiğini veya nelerin olduğunu döndürmezler.
  • Hata Ayıklaması Daha Zor: Bir görevi hata ayıklamak, uzun bir borulu kabuk komutları zincirinden daha kolay ve daha az zaman alıcıdır.

Ancak, çok fazla varsayım kullanan ve benzer işlevlere sahip kabuk betiklerinden daha zor kullanılabilen özel bir modül kullanmaktansa, kabuk modülünü kullanmanın daha iyi olduğu senaryolar da vardır.

 

 

Yazının orijinalini buradan okuyabilirisniz.

Hüseyin GÜÇ

Kariyerime 26 yıl önce başladım. Windows ve Linux sistemlerinin kurulumu, yapılandırılması, yönetimi ve bakımı dahil olmak üzere birden fazla sistem üzerinde uzmanlaştım. Açık kaynak dünyasındaki en son gelişmelerden haberdar olmaktan ve Linux hakkındaki en son araçları, özellikleri ve hizmetleri denemekten hoşlanıyorum. Son 6 yıldır  sistem ve ağ yöneticisi olarak görev yapıyorum ayrıca Pardus Dönüşüm Projesini yönetiyorum ve Pardus İşletim Sisteminin yaygınlaşması adına uğraş gösteriyorum. Boş zamanlarımda açık kaynaklı uygulamaların Türkçe çevirisine katılıyorum ve The Document Foundation üyesiyim.