How do I read in a file from ansible and get it to return the last few lines? - while-loop

I have a log file that updates over time. After it updates there is a specific line in the log that specifies that the update is complete, near the end of the file. I want to create a task using Ansible that reads in this file and returns the last line of the file, or at least the last few lines. If the line isn't found re read the file (as it means it is still updating). Does anyone know how I can go about this?
I've tried looking at documentation and have made a task that at reads the log file into a variable but I'm not sure where to go from here, or even if this is the right way to do it? Below is what I've done so far. I'm working on a windows machine.
- name: Check Log file
win_shell: cmd /k TYPE C:\Files\logfile.log
register: logFile
Thanks!!!

Here we can use a module called lineinfile although the module is used for a different purpose but it can be used in conjuction to
check_mode: yes which ensure it will not write anything to file ever
until: not presence.changed will do the required looping for you
retries: 5 this is the number of retries, therefore for infinite loop set it to a large number but absolute infinity is not encouraged here!
- name: find
lineinfile:
path: /PATH/TO/LOG_FILE
line: 'registering Mbean....'
check_mode: yes
register: presence
until: not presence.changed
retries: 5
delay: 10
UPDATE: #zeitounator suggestion in comments of the question looks cleaner and is implemented below
- name: WAIT
wait_for:
path: /PATH/TO/LOG_FILE
search_regex: 'registering Mbean....'

Related

monit check file for removed content

I'm trying to check some config, which should contain combination: "^UseBridges".
And i know, that file can be changed after somewhat editing via admin UI, but UI doesn't support feature i need.
So i'm trying to write monit check for it, so it will check config, and if confeg resetted, it will add some needed strings to the end of config.
I've tried next rules:
check file torrc with path "/root/t" if content != '^UseBridges' then alert
and
check file torrc with path "/root/t" if not match '^UseBridges' then alert
Both syntaxes looks correct, but doesn't work the way i expect.
If i remove "!" or "not" - it works as expected. It finds string and execute action.
But if i want to check that removal of string - nothing happens.
What is wrong?
Or monit doesn't support that?
The Monit does not support that.
But if i want to check that removal of string - nothing happens.
What is wrong? Or monit doesn't support that?
Monit read the content of the file and keep the position of the last line in mind. With the next cycle additional lines are read etc.. If the file size became smaller, Monit start reading from the beginning.
Monit can not find deleted lines, because Monit does not compare file, Monit check the occurrence of a string only.

What are the conditions for snakemake to execute a job?

I would like to know all necessary criteria required for snakemake to decide that a job needs to be executed, but I couldn't find them in their documentation. The best source I have found is in snakemake author's slides from 2016, which says:
A job is executed if and only if
- output file is target and does not exist
- output file needed by another executed job and does not exist
- input file newer than output file
- input file will be updated by other job
- execution is enforced
However it appears he has stopped using that slide since then, which makes me wonder if above criteria have changed now.
This page of their documentation has a link to the slides from 2019: https://snakemake.readthedocs.io/en/stable/tutorial/tutorial.html. On the page 26 of the slides you may see the same set of rules: https://slides.com/johanneskoester/snakemake-tutorial#/25:
Job execution
A job is executed if and only if
- output file is target and does not exist
- output file needed by another executed job and does not exist
- input file newer than output file
- input file will be updated by other job
- execution is enforced
determined via breadth-first-search on DAG of jobs
I guess that nothing has changed in these rules since 2019, especially taking in the consideration that this presentation is referenced from the official tutorial page.

Automic: How to implement Error-Handling in Script

I want to check a file in Unix via Automic. If the file doesnt exist it should switch the host and check if the file is there.
The problem is, that I dont now how to implement a error handling.
Everytime the script object is processing and cant find the file the skript aborted. I need a new starting point in the skript but "ON_ERROR" or ":RESTART" doesnt work.
How can I implement a logic like this: IF the script aborted due to the error-massage 'No such file or directory'start the script from here instead.
Thank you very much for your help!
Best regards
I have solved it. Use the function PREP_PROCESS_FILENAME to check if the file exists in the folder!
You have to start the task twice in the same workflow. The task-job checks if the script exists otherwise nothing to do.
if [ -f "/path/to/script" ]
then
bash /path/to/script
else
echo "Script not found"
fi
In Post-Script you can modify the state for the empty task with :MODIFY_STATE. Depend on report or returncode

lineinfile module not acting appropriately with Ansible variable dictionary

My code is removing all instances of socket variables in my.cnf file and then repopulating the file with the correct variable and file location.
The deletion portion is working correctly, however the insert quits after the first line. So it will insert the correct 'socket' line directly under [mysqladmin] but it won't add to the remaining sections of the file.
- name: modify my.cnf setting
hosts: dbservers
remote_user: dbuser
become: yes
tasks:
- name: delete old socket definitions
lineinfile:
dest: /etc/mysql/my.cnf
regexp: "^socket "
state: absent
- name: add new socket variable
lineinfile:
dest: /etc/mysql/my.cnf
line: "{{ item.line }}"
insertafter: "{{ item.insertafter }}"
with_items:
- { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqladmin\]' }
- { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysql\]' }
- { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqldump\]' }
- { line: 'socket = /mysql/run/mysqld.sock', insertafter: '^\[mysqld\]' }
On an additional note, I'd like there to be a line of space between the header and the new socket declaration if that is at all possible.
I've tried with version 2.0.2 and 2.2.0 and neither are behaving as intended.
The lineinfile works as it should (see #techraf's answer).
Your task is:
My code is removing all instances of socket variables in my.cnf file and then repopulating the file with the correct variable and file location.
Why not use replace then?
- replace:
dest: /etc/mysql/my.cnf
regexp: '^socket.*$'
replace: 'socket = /mysql/run/mysqld.sock'
Keep in mind:
It is up to the user to maintain idempotence by ensuring that the same pattern would never match any replacements made.
So you may want to change regexp ^socket.*$ to something that matches only "wrong" values that should be replaced to prevent unnecessary changed state of the task.
Ansible works exactly as intended. lineinfile module is used to ensure a particular line is in the specified file. The name of the module describes its function literally: "line in a file". It's not "lines in a file" or "line in a part of a file".
You specify only one pattern for the line:
socket = /mysql/run/mysqld.sock
so after Ansible ensured it exists (likely inserting it), all further calls to "ensure it exists" will not insert it again, because it already exists (that's how declarative programming works).
It doesn't matter that you specify a different insert_after values, because the like is the same and insert_after is not a part of the condition.
Although you don't show the exact syntax of your configuration file, it looks like an INI-style formatting (it also looks like a regular MySQL option file, which is an INI file), thus you may try using ini_file module instead.

Inconsistent Behavior In A Batch File's For Statement

I've done very little with batch files but I'm trying to track down a strange bug I've been encountering on a legacy system.
I have a number of .exe files in particular folder. This script is supposed to duplicate them with a different file name.
Code From Batch File
for %%i in (*.exe) do copy \\networkpath\folder\%%i \\networkpath\folder\%%i.backup.exe
(Note: The source and destination folders are THE SAME)
Example Of Desired Behavior:
File1.exe --> Becomes --> File1.exe.backup.exe
File2.exe --> Becomes --> File2.exe.backup.exe
Now first, let me say that this is not the approach I would take. I know there are other (potentially more straight forward) ways to do this. I also know that you might wonder WHY on earth we care about creating a FileX.exe.backup.exe. But this script has been running for years and I'm told the problem only started recently. I'm trying to pinpoint the problem, not rewrite the code (even if it would be trivial).
Example Buggy Output:
File1.exe.backup.exe
File1.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
File1.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
etc...
File2.exe.backup.exe
File2.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
File2.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe.backup.exe
Not knowing anything about batch files, I looked at this and figured that the condition of the for statement was being re-evaluated after each iteration - creating a (near) infinite loop of copying (I can see that, eventually, the copy will fail when the names get too long).
This would explain the behaviour I'm seeing. And when cleaned the directory in question so that it had only the original File1.exe file and ran the script it produced the bug code. The problem is that I CANNOT replicate the behaviour anywhere else!?!
When I create a folder locally with a few .exe files and run the script - I get the expected output. And yes, if I run it again, I get one instance of 'File1.exe.backup.exe.backup.exe' (and each time I run it again, it increases in length by one). But I cannot get it to enter the near-infinite loop case.
It's been driving me crazy.
The bug is occurring on a networked location - so I've tried to recreate it on one - but again, no success. Because it's a shared network location, I wondered if it could have something to do with other people accessing or modifying files in the folder and even introduced delays and wrote a tiny program to perform actions in the same folder - but without any success.
The documentation I can find on the 'for' statement doesn't really help, but all of the tests I've run seem to suggest that the in (*.exe) section is only evaluated once at the beginning of execution.
Does anyone have any suggestions for what might be going on here?
I agree with Andriy M's comment - it looks to be related to Windows 7 Batch Script 'For' Command Error/Bug
The following change should fix the problem:
for /f "eol=: delims=" %%i in ('dir /b *.exe') do copy \\networkpath\folder\%%i \\networkpath\folder\%%i.backup.exe
Any file that starts with a semicolon (highly unlikely, but it can happen) would be skipped with the default EOL of semicolon. To be safe you should set EOL to some character that could never start a file name (or any path). That is why I chose the colon - it cannot appear in a folder or file name, and can only appear after a drive letter. So it should always be safe.
Copy supports wildcard characters also in target path. You can use
copy \\networkpath\folder\*.exe \\networkpath\folder\*.backup.exe