How to "skip" a task in rake - ruby

When building files with rake, the build system is smart enough to tell whether or not it needs to actually run a task if e.g. the file already exists and the dependencies are not more recent.
Is there a standard way to skip other tasks? I'm thinking of something maybe like
task :containers do
sh "docker-composer up"
end
# the following doesn't exist
task :containers, if: `docker ps | grep mycontainer`.empty?

You can use the next keyword to "skip out" of a task whenever you want, e.g.
task :containers do
next if `docker ps | grep mycontainer`.empty?
sh "docker-composer up"
end
and that won't interrupt the flow of other tasks in the queue.
Alternatively, you could just wrap your task code in an if statement inside the task definition, and maybe print something out if the condition fails.

Related

How to skip a always running task in airflow after few hours?

My example DAG:
Task1-->Task2-->Task3
I have a pipeline with a BashOperator task that should not stop (at least for a few hours).
Task1: It watches a folder for zip files and extracts them to another folder
#!/bin/bash
inotifywait -m /<path> -e create -e moved_to|
while read dir action file; do
echo "The file '$file' appeared in directory '$dir' via '$action'"
unzip -o -q "/<path>/$file" "*.csv" -d /<output_path>
rm path/$file
done
Task2: PythonOperator(loads the CSV into MySQL database after cleaning)
The problem is that my task is always running due to the loop, and I want it to proceed to the next task after (execution_date+ x hours).
I was thinking of changing the trigger rules of the downstream task.I have tried the execution_timeout in BashOperator but the task shows as failed on the graph.
What should be my approach to solve this kind of problem?
There are several ways to address the issue you are facing.
Option 1: Use execution_time on parent task and trigger_rule='all_done' on child task. This is basically what you suggested but just for clarifications - Airflow doesn't mind that one of the task in the pipeline has failed. In your use case you describe it as a valid state for the task so it's OK but not very intuitive as people often associate failed with something that is wrong so it's understandable that this is not the preferred solution.
Option 2: Airflow has AirflowSkipException. You can set timer in your python code. If timer exceed the time you defined then do:
from airflow.exceptions import AirflowSkipException
raise AirflowSkipException(f"Snap. Time is OUT")
This will set parent task to status Skipped then the child task can use trigger_rule='none_failed'. In this way if parent task fails it's due to an actual failure (but not timeout). Valid execution will yield either success status or skipped.

why rake tasks are not executing using and operator?

I have a rake task :
task :kill_process do
system %q(ps -ef | awk '{if($8~"java" || $8~"glassfish" || $8~"ruby" || $8~"god" || $8~"couch"){printf("Killing : %s \n",$2);{system("kill -9 "$2)};}}')
end
This is basically killing processes. And this task is a part of another rake task :
desc "stop the entire system"
task :stop => [...., :kill_process]
There's another task:
desc "start the entire system"
task :start => [....]
When I am doing rake stop && rake start
stop task is executed successfully. but rake start is not executing.
If i execute both tasks separately, then it works fine. but not in rake stop && rake start
What will be better to use here exec function or system or any other, please suggest me.
My only requirement is to kill these mentioned processes at the end of rake stop. But also it should not effect other things like rake stop && rake start should work fine.
As mentioned in the comments, the exit code is 137 which evaluates to false and therefore the other part of the && does not get executed. The reason for this is probably kill -9.
There are a few options now.
Return 0 from your rake task, something like exit(0)
Don't use kill -9
Create restart command which does execute stop and start but without logically depending on each other (&&).
Exit code 137 indicates that a process has received a SIGKILL signal and was thus killed from the outside.
This happens since a Rake task is also executed by Ruby. As such, your stop task is sending a SIGKILL to its own process too (along with all other Ruby processes on the system). Now, since you have specified that you only want to execute the rake start process if the previous process was successful (i.e. had a exit code of 0), your shell doesn't start the rake task.
To quickly fix this, you can instead run rake stop; rake start, i.e run the two processes regardless of their individual exit codes (by default).
However, a better idea would probably to make your stop task more explicit and only kill the specific processes you need rather than everything in sight which looks slightly like a related process. This will likely result in a more stable system overall too when you don't kill potentially unrelated processes all the time.

Is there any way to get more details of a ansible task

ansible-playbook —list-tasks —tag<tagname>
Lists the tasknames. Is there way to get more details of task other than name?
If you want to see the end result of each task without executing the tasks,
Ansible provides a check mode, also called dry run mode that predicts the changes that may occur in each task without actually executing it.
ansible-playbook --check your_playbook.yaml

How to resume execution of playbook from same place where it failed?

I am running a playbook for deployment of nodes.Suppose because of some issue like power failure or some other exception, the execution failed after executing some tasks.So, I am trying to resume the execution from same place where it failed, when I run the playbook next time.
It is time consuming to run the playbook for all the task from start.Is it possible to achieve the solution?
You can use function --start-at-task="task name" this will run the whole playbook from the specific task name and continue from there om. But be careful, if you have registered any variables in tasks before and use them afterwards, starting at that task will not register them and therefore the play will not use them. In that case you could give tag "always" to the tasks that register variables
The output of a failed ansible-playbook run actually tells you how to do this (assuming you have 'retry_files_enabled' set true in your config, which is the default):
to retry, use: --limit #/some/path/to/a/retry/file
In the case of a failure, Ansible will create a retry file, which is for the specific purpose of what you requested. Therefore, just append the '--limit' statement to the command you used to run the playbook and kick it off again.
Edit: To be fair, your specific case of a power failure on the control machine would not be covered by this, but any failure that Ansible handles (i.e. the majority), will work with this method.
execute like this:
ansible-playbook --forks=10 myscript.yml --start-at-task='install java'
with limit: ansible-playbook --forks=10 myscript.yml --limit limit1 --start-at-task='install java'

How to query for Ruby scripts currently running on Unix?

I have a few Ruby scripts: a.rb, b.rb and c.rb. These scripts are called from corresponding wrapper shell scripts: a.sh, b.sh and c.sh.
All these scripts are in a distributed environment:
`a.sh` and `a.rb` are on serverA
`b.sh` and `b.rb` are on serverB
`c.sh` and `c.rb` are on serverC
I need to write a script call.rb and its wrapper call.sh script, which should check for all the scripts currently running on the distributed environment.
I have the logic which will determine the different hosts that I have and how to communicate to these different hosts.
When any Ruby script is running, the command:
ps aux
shows:
ruby a.rb
I have no ideas on how to query for different scripts currently running. One thing to note is that there might be other Ruby scripts running in the system too, but I need to check only for a.rb, b.rb, or c.rb.
If you're doing a heartbeat check, or setting up a keep-alive check, why not have the files save their PID to a file at their startup, and then delete it when they quit?
The building blocks are:
$$ is the current process ID for a running script.
Ruby will run a block named BEGIN {} at start-up, before variables are defined. You can use that to create a PID file. Typically we use something like "#{ File.basename($0) }.pid" to create the filename.
Ruby will run a block named END {} at shut-down, as a last task. You can use that to remove the PID file.
Put the PID files in a well-known place. Where that is is left as an exercise for you to figure out for your OS.
Have your watchdog scan those, grab the PIDs, scan the process list for the PID IDs, possibly correlating them to the name of the pid file.
You can figure out more icing to put on your cake.
You can simply execute commands via SSH like this:
ssh user#host "ps -ef | grep '(ruby|[^.]+\.rb)'"
Grepping the output of ps for the script names would also work:
ps -ef | grep '(a.rb|b.rb|c.rb)'
Edit: If you don't want grep itself to show up in the process list, filter it like this:
ps -ef | grep '(a.rb|b.rb|c.rb)' | grep -v grep
If you want to solve this in Ruby, you could use a process monitoring tool like God. Monit, Bluepill or Eye

Resources