2
votes

Ansible: insérer un mot dans la ligne de commande GRUB

Je voudrais utiliser le module lineinfile ou replace d'Ansible afin d'ajouter le mot splash à la cmdline dans GRUB.

Cela devrait fonctionner pour tous les exemples suivants:

Exemple 1:

  • Avant: GRUB_CMDLINE_DEFAULT=""
  • Après: GRUB_CMDLINE_DEFAULT="splash"

Exemple 2:

  • Avant: GRUB_CMDLINE_DEFAULT="quiet"
  • Après: GRUB_CMDLINE_DEFAULT="quiet splash"

Exemple 3:

  • Avant: GRUB_CMDLINE_DEFAULT="quiet nomodeset"
  • Après: GRUB_CMDLINE_DEFAULT="quiet nomodeset splash"

Le post Ansible: insérer un seul mot sur une ligne existante dans un fichier expliquait bien comment cela pouvait être fait sans guillemets. Cependant, je ne peux pas lui faire insérer le mot entre les guillemets.

Quelle est l'entrée requise dans le rôle ou le playbook Ansible pour ajouter le mot splash à la cmdline comme indiqué?


1 commentaires

Si vous souhaitez inclure des guillemets doubles dans une chaîne, utilisez simplement des guillemets simples à l'extérieur: 'Here is "an example" that contains double qutoes'


3 Réponses :


0
votes

Une solution possible est la définition de deux entrées comme suit:

- name: "Checking GRUB cmdline"
  shell: "grep 'GRUB_CMDLINE_LINUX_DEFAULT=.*splash.*' /etc/default/grub"
  register: grub_cfg_grep
  changed_when: false
  failed_when: false

- name: "Configuring GRUB cmdline"
  replace:
    path: '/etc/default/grub'
    regexp: '^GRUB_CMDLINE_LINUX_DEFAULT="((\w.?)*)"$'
    replace: 'GRUB_CMDLINE_LINUX_DEFAULT="\1 splash"'
  when: '"splash" not in grub_cfg_grep'

Explication: Nous vérifions d'abord si le mot-clé splash est présent dans la ligne requise à l'aide de grep. Puisque grep donne un code de retour négatif lorsqu'une chaîne n'est pas trouvée, nous failed_when: false les erreurs en utilisant failed_when: false . La sortie de grep est enregistrée dans la variable grub_cfg_grep .

Ensuite, nous lions le module replace à la condition que le mot-clé splash soit dans la sortie standard de grep. L'expression régulière prend l'ancien contenu entre guillemets et ajoute le mot-clé splash derrière.

Remarque: dans le cas d'une chaîne vide avant l'exécution, le résultat lit " splash" (avec un espace devant) mais c'est toujours une cmdline valide.


0 commentaires

1
votes

La difficulté est cette ligne dans la page du module de remplacement: "C'est à l'utilisateur de maintenir l'idempotence en s'assurant que le même modèle ne correspondrait jamais aux remplacements effectués." https://docs.ansible.com/ansible/latest/modules/replace_module.html#id4 Il est facile d'insérer l'élément mais en fait assez difficile de le rendre idempotent, le fichier cible ne grossit pas à chaque fois que vous exécutez la tâche .

J'ai trouvé un moyen de le faire d'un seul coup avec le module de remplacement. Vous devriez pouvoir adapter cela. Ma tâche vérifie la ligne GRUB_CMDLINE_LINUX_DEFAULT pour "vt.default_red" et insère des codes de couleur si non trouvés.

Ma méthode consistait à copier-coller divers exemples presque là-bas dans le site Web du testeur d'expression régulière et à jouer du violon jusqu'à ce que cela fonctionne. Je ne connais toujours pas le résultat, mais cela a fonctionné dans mes tests sur https://www.regextester.com/ et cela fonctionne dans mon playbook.

Un problème que j'ai eu était que l'implémentation de regex d'Ansible ne prend apparemment pas en charge les conditions, ce qui m'a donné des erreurs étranges pendant un certain temps.

(                            - open capture group #1 (creates backref #1)
 (:?                         - open a non-capturing group (not sure what the question mark is here)
    (?!                      - negative lookahead (ie. don't match if the following string comes next)
       vt\.default_red       - the string to look for, literal dot is escaped
                      )      - close negative lookahead
                       .)    - match a single char (why?) and close the non-capturing group
                         *   - try to match the non-capturing group zero or more times
                          ?  - ... lazily (ie. get the smallest possible match)
                           ) - close capture group #1

L'expression régulière correspond à la chaîne littérale ("GRUB_CMDLINE_LINUX_DEFAULT =" et un guillemet double) au début et le guillemet double à la fin. Déconstruire le reste ...

- name: colours | configured grub command
  replace:
    path: /etc/default/grub
    regexp: '^GRUB_CMDLINE_LINUX_DEFAULT="((:?(?!vt\.default_red).)*?)"$'
    replace: 'GRUB_CMDLINE_LINUX_DEFAULT="\1 vt.default_red=0xee,..."'


0 commentaires

0
votes

Vous pouvez le faire sans sortie shell , avec 2 modules lineinfiles .

Dans votre exemple, vous recherchez splash :

- name: check if splash is configured in the boot command
  lineinfile:
    backup: true
    path: /etc/default/grub
    regexp: regexp: '^GRUB_CMDLINE_LINUX=".*splash'
    state: absent
  check_mode: true
  register: grub_cmdline_check
  changed_when: false

- name: insert splash if missing
  lineinfile:
    backrefs: true
    path: /etc/default/grub
    regexp: "^(GRUB_CMDLINE_LINUX=\".*)\"$"
    line: '\1 splash"'
  when: grub_cmdline_check.found == 0
  notify: update grub

L'astuce consiste à essayer de supprimer la ligne si nous pouvons trouver splash quelque part, mais en ne vérifiant que check_mode: true . Si le terme a été trouvé ( found > 0), nous n'avons pas besoin de mettre à jour la ligne. S'il n'est pas trouvé, cela signifie que nous devons l'insérer. Nous l'ajoutons à la fin avec les backrefs.


0 commentaires