ansible: कई लाइनों के लिए लाइनइनफाइल?


162

उसी तरह lineinfileएक फ़ाइल में एक लाइन जोड़ने के लिए एक मॉड्यूल है, क्या कई लाइनों को जोड़ने का एक तरीका है?

मुझे एक टेम्पलेट का उपयोग नहीं करना है क्योंकि आपको पूरी फ़ाइल प्रदान करनी है। मैं सिर्फ एक मौजूदा फ़ाइल में कुछ जोड़ना चाहता हूं बिना जरूरी जाने कि फाइल में पहले से क्या है इसलिए एक टेम्पलेट एक विकल्प नहीं है।


मैं समझता हूं कि आप उपयोग नहीं करना चाहते हैं template, लेकिन उपयोग lineinfileकरना एक एंटीपैटर्न है । यह एक मजबूत लाल झंडा भी है जिसे आप "फ़ाइल में क्या है" नहीं जानते हैं, जिससे अज्ञात विफलताओं का पर्याप्त जोखिम होता है।
tedder42

39
यह एक विरोधी पैटर्न नहीं है। लाइनइनफाइल का बिंदु एक ही फ़ाइल का प्रबंधन करने वाले कई स्रोतों का समर्थन करना है, जो कभी-कभी अपरिहार्य है। अधिकांश कॉन्फ़िगरेशन फ़ाइलों का एक निश्चित प्रारूप होता है और टकराव से बचने के लिए तर्क आमतौर पर बहुत अधिक नहीं होते हैं।
डग एफ

मुझे नहीं पता कि मेरे पीसी पर बड़ी संख्या में फाइलें क्या हैं; इसका मतलब यह नहीं है कि मैं उन सभी को मिलाना चाहता हूं!
DylanYoung

जवाबों:


222

आप इसे करने के लिए एक लूप का उपयोग कर सकते हैं । यहाँ with_itemsलूप का उपयोग करके एक उदाहरण दिया गया है :

- name: Set some kernel parameters
  lineinfile:
    dest: /etc/sysctl.conf
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  with_items:
    - { regexp: '^kernel.shmall', line: 'kernel.shmall = 2097152' }
    - { regexp: '^kernel.shmmax', line: 'kernel.shmmax = 134217728' }
    - { regexp: '^fs.file-max', line: 'fs.file-max = 65536' }

सुनिश्चित करें कि आपके पास पंक्ति = और rexxp = उद्धरण में तर्क है । मैंने नहीं किया और मैं मिलता रहा msg: this module requires key=value arguments। दिए गए उदाहरण में यह सही है - मैंने अभी उदाहरण का पालन नहीं किया।
जेडीएस

1
क्या मैं पूछ सकता हूं कि पहले परिवर्तन से पहले एक ही बैकअप कैसे किया जाए? शायद आइटम.बैकअप? : D
tdihp

6
यह संभवतः अंसिबल 2.0 से पहले मतदान किया गया था। एक बेहतर जवाब अब है: stackoverflow.com/a/28306576/972128
kkurian

@kkुरियन निश्चित रूप से केवल अगर आप सम्मिलित कर रहे हैं, न कि यदि आप प्रतिस्थापित कर रहे हैं?
ndtreviv

7
@kkurian ब्लॉकइनफाइल समाधान काम नहीं करेगा यदि आपको उदाहरण के लिए एक json फाइल में कुछ लाइनें जोड़ने की जरूरत है और अन्य मार्कर नहीं चाहते हैं। जब आप मार्करों को "" पर सेट कर सकते हैं, तो ansible blockinfile अभी भी मार्करों की तलाश करेगा, कोई खोज नहीं करेगा, और फिर से ब्लॉक डालें। इस प्रकार, मार्करों के बिना ब्लॉकिनफाइल आलसी नहीं है, लूप के साथ लाइनइनफाइल है।
बेतुका

176

आप blockinfileइसके बजाय प्रयोग करके देख सकते हैं ।

आप कुछ ऐसा कर सकते हैं

- blockinfile: |
    dest=/etc/network/interfaces backup=yes
    content="iface eth0 inet static
        address 192.168.0.1
        netmask 255.255.255.0"

8
blockinfileमॉड्यूल शानदार हर बार जब मैं इसका इस्तेमाल करने के लिए चुना है बाहर काम किया है। मुझे विशेष रूप से insertafter/ insertbeforeविकल्पों के सहज व्यवहार से प्यार है ।
जे टेलर टेलर

9
उच्चतम-मतदान का उत्तर शायद अंसिबल 2.0 से पहले था, लेकिन यह अब अधिक सही उत्तर है।
विलेम वैन केटविच

11
ब्लॉकिनफाइल को मार्करों की आवश्यकता होती है। यह कभी-कभी कोई विकल्प नहीं होता है।
छत

1
क्या हम सामग्री को ओवरराइट करने में सक्षम हैं blockinfile?
पामारोल

1
इसका एक सही तरीका यह है कि मुझे लगता है। docs.ansible.com/ansible/blockinfile_module.html
पाउलो विक्टर

20

यदि आपको अद्वितीय गुण = मान रेखाओं के एक सेट को कॉन्फ़िगर करने की आवश्यकता है, तो मैं एक अधिक संक्षिप्त लूप की सिफारिश करता हूं। उदाहरण के लिए:

- name: Configure kernel parameters
  lineinfile:
    dest: /etc/sysctl.conf
    regexp: "^{{ item.property | regex_escape() }}="
    line: "{{ item.property }}={{ item.value }}"
  with_items:
    - { property: 'kernel.shmall', value: '2097152' }
    - { property: 'kernel.shmmax', value: '134217728' }
    - { property: 'fs.file-max', value: '65536' }

एलिक्स एक्सल द्वारा सुझाए गए अनुसार एक तानाशाह का उपयोग करना और मिलान से स्वचालित रूप से हटाने के लिए प्रविष्टियों को टिप्पणी करना,

- name: Configure IPV4 Forwarding
  lineinfile:
    path: /etc/sysctl.conf
    regexp: "^#? *{{ item.key | regex_escape() }}="
    line: "{{ item.key }}={{ item.value }}"
  with_dict:
    'net.ipv4.ip_forward': 1

2
यदि आप with_dict का उपयोग करते हैं तो यह अधिक संक्षिप्त होगा।
एलिक्स एक्सल

18

यहाँ समाधान का एक शोर-मुक्त संस्करण है जो with_items का उपयोग करना है:

- name: add lines
  lineinfile: 
    dest: fruits.txt
    line: '{{ item }}'
  with_items:
    - 'Orange'
    - 'Apple'
    - 'Banana' 

प्रत्येक आइटम के लिए, यदि आइटम fruit.txt में मौजूद है, तो कोई कार्रवाई नहीं की जाती है।

यदि आइटम मौजूद नहीं है, तो इसे फ़ाइल के अंत में जोड़ा जाएगा।

बहुत आसान।


इसे सम्मिलित रूप से नहीं जोड़ा जा सकता है।
ceving

यदि एक से अधिक लाइन गायब हैं, तो मैं चाहूंगा कि आइटम एक क्रम में दिखाई दे। मैं उस आदेश के बारे में कैसे सुनिश्चित कर सकता हूं जिसमें आइटम संलग्न हैं?
MUY बेल्जियम

5

यह आदर्श नहीं है, लेकिन आपको कई कॉल करने की अनुमति है lineinfile। उस का उपयोग करके insert_after, आप इच्छित परिणाम प्राप्त कर सकते हैं:

- name: Set first line at EOF (1/3)
  lineinfile: dest=/path/to/file regexp="^string 1" line="string 1"
- name: Set second line after first (2/3)
  lineinfile: dest=/path/to/file regexp="^string 2" line="string 2" insertafter="^string 1"
- name: Set third line after second (3/3)
  lineinfile: dest=/path/to/file regexp="^string 3" line="string 3" insertafter="^string 2"

5
हाँ, लेकिन यह अभी भी एक समय में एक पंक्ति है। अगर मेरे पास 15 लाइनें हैं, तो मैं उन्हें केवल एक कमांड के साथ जोड़ना पसंद करूंगा। यह संभव नहीं लगता है।
माइकल

1
धन्यवाद। ऐसा लगता है कि यह अभी भी केवल / से पहले के बाद डालने के साथ कई लाइनों को करने का एकमात्र तरीका है।
समयसीमा

5

मैं \nलाइन पैरामीटर का उपयोग करके ऐसा करने में सक्षम था ।

यह विशेष रूप से उपयोगी है यदि फ़ाइल को मान्य किया जा सकता है, और एकल पंक्ति को जोड़ने से एक अमान्य फ़ाइल उत्पन्न होती है।

मेरे मामले में, मैं जोड़ने था AuthorizedKeysCommandऔर AuthorizedKeysCommandUserकरने के लिए sshd_config निम्न आदेश के साथ,:

- lineinfile: dest=/etc/ssh/sshd_config line='AuthorizedKeysCommand /etc/ssh/ldap-keys\nAuthorizedKeysCommandUser nobody' validate='/usr/sbin/sshd -T -f %s'

विकल्पों में से केवल एक को जोड़ने से एक फ़ाइल उत्पन्न होती है जो सत्यापन विफल हो जाती है।


12
यह प्लेबुक चलने पर हर बार एक अतिरिक्त लाइन बनाएगी - यह सही रूप से नहीं पहचानती है कि लाइन पहले से मौजूद है। कम से कम, मेरे लिए यह मामला 1.7.1 पर है
डेविड

1
मैंने एक बग की सूचना दी , लेकिन Ansible लोगों को इसे ठीक करने में कोई दिलचस्पी नहीं है।
छत

1
एक नया ब्लॉकइनफाइल मॉड्यूल है जो उस समाधान से बेहतर होना चाहिए। ( Docs.ansible.com/ansible/blockinfile_module.html )
Penz

1

कई पंक्तियों को जोड़ने के लिए आप ब्लॉकफ़ाइल का उपयोग कर सकते हैं:

- name: Add mappings to /etc/hosts
  blockinfile:
    path: /etc/hosts
    block: |
      '10.10.10.10  server.example.com'
      '10.10.10.11  server1.example.com'

एक लाइन जोड़ने के लिए आप लिनिफाइल का उपयोग कर सकते हैं:

- name: server.example.com in /etc/hosts
  lineinfile:
    path: /etc/hosts
    line: '192.0.2.42 server.example.com server'
    state: present

1

कई लाइनों को जोड़ने के लिए आप इसे सरल बनाने के लिए यहाँ वैरिएबल सहित lineinfileमॉड्यूल का उपयोग कर सकते हैं :)with_itemsvars

---
- hosts: localhost  #change Host group as par inventory
  gather_facts: no
  become: yes
  vars:
    test_server: "10.168.1.1"
    test_server_name: "test-server"
    file_dest: "/etc/test/test_agentd.conf"

  - name: configuring test.conf
    lineinfile:
      dest: "{{ item.dest }}"
      regexp: "{{ item.regexp }}"
      line: "{{ item.line }}"
    with_items:
      - { dest: '"{{ file_dest }}"', regexp: 'Server=', line: 'Server="{{test_server}}"' }
      - { dest: '"{{ file_dest }}"', regexp: 'ServerActive=', line: 'ServerActive="{{test_server}}"' }
      - { dest: '"{{ file_dest }}"', regexp: 'Hostname=', line: 'Hostname="{{test_server_name}}"' }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.