lineinfile - append at end of line ?

can lineinfile append at the end of a line ?

I have a kernel line in my grub.conf i would like to append “pcie_aspm=off” to if it’s not there.

To my understanding backrefs would possibly be able to do that ?

I don’t wanna template up grub.conf just for that small addition, but do not want to replace the whole kernel line either as it might not be 100% the same on all my systems.

Yes, you should be able to do that by specifying EOF as the insertafter= argument.

James,

EOF is end of file, he wants to add to the end of the line.

The module is not that smart right now, at least according to docs.

–Michael

Yes this is possible with backrefs - aka capturing groups- and not just at the end of the line.
one possibility is to leverage negative lookahead regexp [1]
then one call to lineinfile is enough.

warning, the regexp can be quite complex

here is a simplified l example of a configuration file that has a line
starting with something like
OPTIONS=“-a option1 -b another:option -x -z athird.option”

the point is to check if -x is NOT there and add it as the first option (could have been added at the end by swapping -x and \1)

lineinfile: dest=${target_file}
backrefs=True
state=present
regexp=‘^OPTIONS=“(([^-](-(?!x).)+[^-])*)”’
line=‘OPTIONS=“-x \1”’

works well since ansible 1.1
requires the line you have to match has a well specified format
in your case it is :

kernel

you are looking for options not being pcie_aspm=off

[1] see http://docs.python.org/2/library/re.html

good luck

Thanks for this example! , Lineinfile is very powerful, but documentation and regex does not explain it explicitly. Like how to use backrefs and more detailed examples for these would be great! (Like how to add stuff to end of line, start of the line, before/after the regex, replace line and EOF/BOF)

Docs are open source so we do take patches.

See the lineinfile source code for what builds the inline docs.

Thanks, that confirmed what I feared :slight_smile: strange regex options to do something somewhat simple.

I hope someone will be able to document this better in the future, or make a simpler way to do this. Then again I have no clue if anyone other than me would find this useful.
Until then I will stick to a sed command to not pull my already grey hair completely away :slight_smile:

I understand the hair concern … :wink:

Needed that in some of the playbooks we have.

More generally needed when in “remediation contexts” to insure other
changes made by sysadmin are not removed (after original deployment)

This is pure regex thing (python or sed or …), not an ansible issue.

the lineinfile module doc already specified this is Python regexp

Agree that some well documented examples will help,
but it will be more about explaining regexp compexity than anything else

Phil

I should say it’s almost always better to just template the file unless you think the user is going to alter it.

In any event, I’ll remind everyone the examples and documentation are open source. The source to the module contains the docstring that gets rendered, so additional examples (as well as patches) are welcome, and easily added!

It’s hard for me to tell what the best way to explain something to someone else is sometimes, so it’s usually best for those who figure things out to submit something. In some cases we may edit/polish things up a bit or have some comments or suggestions of things to add.

Thanks!

Agree with Michael on the template option

Regarding the request/question from Alex Rodenberg

Below is an example tested with ansible version 1.3.2 whith some hopefully understandable comments about the implementation

HTH

– code extract ----

Regexp implementation note:

- the line to match follows the following pattern:

- : matched by ^

- A number of white spaces/tabs: matched by \s+

- the “kernel” string: matched by kernel

- A list of: <spaces|tab> → this is all the options passed to the kernel

- possible spaces and tabs at the end : matched by the latest \s*

- the : matched by $

- the list of: <spaces|tab> described above

e.g: /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/VolGroup00-root_vol … rd_LVM_LV=VolGroup00/root_vol SYSFONT=latarcyrheb-sun16 rd_NO_DM

is matched by: (\s+(?!pcie_aspm=off)[\w=/-.]+)*

The (?!pcie_aspm=off) is to direct the regexp engine to check that the string ‘pcie_aspm=off’

is not present

anywhere in the in the part. This is called negative lookahead.

This is just a check, no characters are “consumed”. The following [\w=/-.]+

is ther to consume aka match any strings made of alphanumeric characters,the ‘/’, the ‘-’, the ‘.’

- if the ‘pcie_aspm=off’ string is present, there is no match

- the capturing group 1 referred as to \1 in the line= statement

will capture the whole line but the trailing and

  • name: Activate a lacking kernel option ‘pcie_aspm=off’ in {{ targetgrub }}

lineinfile: dest={{ targetgrub }}

backup=True

backrefs=True

state=present

regexp=‘(^\s+kernel(\s+(?!pcie_aspm=off)[\w=/-.]+))\s$’

line=‘\1 pcie_aspm=off’

– end of code extract ----

At least for grub configs I’m not happy with templating, if i fx. do a kernel upgrade it will not point at the right stuff anymore… but that can be templated as well i know :slight_smile:

Thanks for the regexp Phillipe!