Cron Jobs and Rails

Cron

If you’re reading this article, it’s probably because you’ve heard of cron jobs, cron tasks, or crontab. Cron is a piece of software written for *nix-type operating systems to help with the scheduling of recurring tasks. You may want to use cron to schedule certain recurring actions in your Rails application, such as checking each day for expired accounts or clearing out expired sessions from your database.

It’s pretty easy to start working with cron jobs. You can start editing your cron tasks using the crontab command:

1
crontab -e

This will open up a text file in your terminal’s default editor (probably vim or nano). You can change the editor that is used by prefixing the crontab command with an adjustment to the EDITOR variable:

1
EDITOR=nano crontab -e

Remember that your scheduled tasks will be run as the user that you use when you invoke crontab.

Once you’re in the editor, you can start creating and editing cron tasks. To schedule a task, you need to define when the task will run, then define the command to trigger that task. The scheduling syntax has five parts, separated by spaces (diagram taken from drupal.org):

1
2
3
4
5
6
7
# +---------------- minute (0 - 59)
# |  +------------- hour (0 - 23)
# |  |  +---------- day of month (1 - 31)
# |  |  |  +------- month (1 - 12)
# |  |  |  |  +---- day of week (0 - 6) (Sunday=0)
# |  |  |  |  |
  *  *  *  *  *  command to be executed

The parts represent, in this order, the minute(s), hour(s), day(s) of the month, month(s), and day(s) of the week to run the command. You can use the asterisk (*) to represent every unit of the part in question. So using * * * * * schedules your task to run every minute of every hour on every day of every month and on every day of the week. In addition to the asterisk, you can use comma-delimited integers and names of the week. You can also replace the 5 parts with a single predefined schedule, as explained in the wikipedia article on Cron. Once you have your schedule defined, you can follow it with any valid bash command:

1
2
3
4
5
# Every day at midnight and noon, quiely retrieve index.html from example.com, # using wget:
0 0,12 * * * /usr/bin/wget -O -q -t 1 http://example.com/index.html

# Same task, but just once every day
@daily /usr/bin/wget -O -q -t 1 http://example.com/index.html

Running Rails Application Code via Cron

It can be useful to run system and server tasks with cron, but a lot of times you’ll need to run Rails application code on a schedule. You can do this the hard way and set up a controller action (e.g. CronJobsController#some_task) that triggers application code to run, then set up a cron task to send a GET request to that action (e.g. /usr/bin/wget -O -q - -t 1 http://example.com/cron_jobs/some_task), or you can do it the easy way and run the code directly via cron. Rails has runners and rake tasks to facilitate this:

Rake Tasks from Cron

To run an existing rake task, you can change your directory to your application root, then call the rake task:

1
0 0 * * * cd /my/app/root && /path/to/bundle exec rake some_task

You can find the path to your bundle executable by typing which bundle from within your application’s root folder.

There’s no need to limit your rake tasks to ones that are already available via Rails or whatever framework and gems you happen to be using. You can write your own rake tasks and use those in your cron jobs as well. You can find more information about how to write your own rake tasks in the Rails Guides.

Runners

Another way to run code in your Rails app directly from cron is by using Rails runners. To execute rails code using rails runner, all you have to do is call rails runner "ruby code":

1
0 * * * * cd /my/app/root && /path/to/bundle exec rails runner -e production "Model.long_running_method"

The -e production sets the environment to “production”, and can be altered as needed. The Model.long_running_method portion represents a class method that can be called from within your Rails application. Using rails runner to run the code loads up your application into memory first, then evaluates the ruby code in the Rails environment. When the task completes, the runner exits.

Debugging Custom Code

To debug a runner or a custom rake task, you can print to STDOUT from within your code (using puts or similar methods). Within crontab, make sure to set the MAILTO variable to your email address so that you’ll receive that output.

1
2
MAILTO=email@example.com
* * * * * /usr/bin/some_command

As long as the server is set up properly to send outgoing email, you’ll get emailed the output.

The Whenever Gem

One difficulty with using cron is that it is awkward to maintain and store your cron jobs. The syntax can be cumbersome to beginners as well, and it’s easy to make mistakes in setting up your schedules and your executables’ paths. One way to overcome these difficulties is to use the whenever gem. Just add gem 'whenever', require: false to your Gemfile and run bundle install. Then within your application’s root directory, run the following command:

1
bundle exec wheneverize

This will add a schedule file to your config folder (config/schedule.rb). This file is where you set up your scheduled tasks. You can use regular cron scheduling, or you can use a more idiomatic DSL for scheduling. The following examples are take from the gem’s README.md:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
every 3.hours do
  runner "MyModel.some_process"
  rake "my:rake:task"
  command "/usr/bin/my_great_command"
end

every 1.day, :at => '4:30 am' do
  runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end

every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
  runner "SomeModel.ladeeda"
end

every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
  runner "Task.do_something_great"
end

every '0 0 27-31 * *' do
  command "echo 'you can use raw cron syntax too'"
end

# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, :at => '12:20am', :roles => [:app] do
  rake "app_server:task"
end

Once you’ve set up your scheduled tasks in config/schedule.rb, you still need to apply them to your crontab. From your terminal, use the whenever command to update your crontab:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Change to your application's directory.
cd /my/app

# View config/schedule.rb converted to cron syntax
bundle exec whenever

# Update crontab
bundle exec whenever -i

# Overwrite the whole crontab (be careful with this one!)
bundle exec whenever -w

# See all the options for the whenever command
bundle exec whenever -h

There is a capistrano extension for whenever, so if you are using capistrano to deploy your application, make sure you take advantage of it.

Pitfalls of Crontab

While using the whenever gem can fix some of the issues with using cron to manage your application’s recurring tasks, there are several reasons you may want to avoid using cron tasks at all:

  • It’s easy to forget to set up cron tasks on servers.
  • If you are running multiple servers, you may not want them all to run the cron tasks — doing so can cause conflicts or can at least require you to try to handle semaphores/locks in your code. This can get messy fast.
  • Cron schedules are maxed out at minute level. Scheduling for multiple times a minute is impossible.
  • If your server goes down, it could miss a critical scheduled task, so it often becomes a necessity to run cron more frequently and have the code account for missed runs.
  • Cron tasks can be difficult to debug. It is common practice to suppress all output, but by doing so you are possibly taking away a lot of good debugging information.
  • Each time a runner or rake task is run on a Rails app, the entire app has to be loaded into memory, which can take a substantial amount of CPU time and a substantial amount of memory. If your cron tasks start overlapping, you can quickly run out of RAM and cause your server to go kaput.

Despite the above issues, there are some cases where running a cron task is perfectly acceptable and possible better than some of the alternatives. When it is not absolutely essential that the task be run consistently, a cron job can be a quick and easy solution that doesn’t require a lot of setup. Combined with a whenever schedule.rb file and a deployment strategy that maintains your cron tasks, it can be a viable strategy.

Alternatives to Crontab

Sidekiq and Sidetiq

In cases where cron tasks don’t quite cut it, there are alternatives. My personal favorite is a combination of Sidekiq and Sidetiq. Understand, though, that these aren’t simple to setup. They require a redis server and additional code. When you run sidekiq, your application is loaded into memory and runs tasks as you schedule them in your code. This is nice because the code is constantly running and can quickly pick up new tasks and process them without additional overhead. When multiple application servers point to a single redis server (or server cluster) endpoint, you can also have multiple sidekiq instances pointing to that same redis server and have them pick off tasks as they have availability. This is great for scaling and (mostly) eliminates issues of locking, semaphores, and race conditions.

The Heroku Scheduler

Another alternative to cron tasks is the Heroku Scheduler, if your application is running on Heroku. As is noted in the documentation, the Heroku Scheduler does not guarantee that tasks will be run, so you are encouraged to include a custom clock in your application to make sure that tasks are run. It also has a limit of running at most once every 10 minutes, so you may need to use a worker dyno and create your own looping mechanism in a long running task to make sure tasks are run as frequently as they should be.

Conclusion

While cron jobs are useful, and can get the job done in many instances, you should be careful in your decision of how to implement scheduled and delayed tasks. Cron jobs are best for tasks that are not highly critical or essential to your application’s functionality or performance. They should also usually execute in a reasonably short amount of time so that they don’t bog down your server(s). When you have scheduled tasks of a critical nature, or tasks that need to be run more than once per minute, tools such as Heroku’s worker dynos or Sidekiq are very performant and viable solutions.

Linux Cron

Cron allows Linux and Unix users to run commands or scripts at a given date and time. You can schedule scripts to be executed periodically. Cron is one of the most useful tool in a Linux or UNIX like operating systems. It is usually used for sysadmin jobs such as backups or cleaning /tmp/ directories and more. The cron service (daemon) runs in the background and constantly checks the /etc/crontab file, and /etc/cron.*/ directories. It also checks the /var/spool/cron/directory.

Personal note: WordPress uses wp-cron to do this same thing – run command periodically or at a given time (or interval).

crontab command

You need to use the crontab command to edit/create, install, deinstall or list the cron jobs in Vixie Cron. Each user can have their own crontab file, and though these are files in /var/spool/cron/crontabs, they are not intended to be edited directly. You need to use crontab command for editing or setting up your own cron jobs.

Types of cron configuration files

There are different types of configuration files:

  1. The UNIX / Linux system crontab : Usually, used by system services and critical jobs that requires root like privileges. The sixth field (see below for field description) is the name of a user for the command to run as. This gives the system crontab the ability to run commands as any user.
  2. The user crontabs: User can install their own cron jobs using the crontab command. The sixth field is the command to run, and all commands run as the user who created the crontab

Note: This faq features cron implementations written by Paul Vixie and included in many Linux distributions and Unix like systems such as in the popular 4th BSD edition. The syntax is compatible with various implementations of crond.

How Do I install or create or edit my own cron jobs?

To edit or create your own crontab file, type the following command at the UNIX / Linux shell prompt:
$ crontab -e

Do I have to restart cron after changing the crontable file?

No. Cron will examine the modification time on all crontabs and reload those which have changed. Thus cron need not be restarted whenever a crontab file is modified.

Syntax of crontab (field description)

The syntax is:

1 2 3 4 5 /path/to/command arg1 arg2

OR

1 2 3 4 5 /root/backup.sh

Where,

  • 1: Minute (0-59)
  • 2: Hours (0-23)
  • 3: Day (0-31)
  • 4: Month (0-12 [12 == December])
  • 5: Day of the week(0-7 [7 or 0 == sunday])
  • /path/to/command – Script or command name to schedule

Easy to remember format:

* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Your cron job looks as follows for system jobs:

1 2 3 4 5 USERNAME /path/to/command arg1 arg2

OR

1 2 3 4 5 USERNAME /path/to/script.sh

Example: Run backup cron job script

If you wished to have a script named /root/backup.sh run every day at 3am, your crontab entry would look like as follows. First, install your cronjob by running the following command:
# crontab -e
Append the following entry:
0 3 * * * /root/backup.sh
Save and close the file.

More examples

To run /path/to/command five minutes after midnight, every day, enter:
5 0 * * * /path/to/command
Run /path/to/script.sh at 2:15pm on the first of every month, enter:
15 14 1 * * /path/to/script.sh
Run /scripts/phpscript.php at 10 pm on weekdays, enter:
0 22 * * 1-5 /scripts/phpscript.php
Run /root/scripts/perl/perlscript.pl at 23 minutes after midnight, 2am, 4am …, everyday, enter:
23 0-23/2 * * * /root/scripts/perl/perlscript.pl
Run /path/to/unixcommand at 5 after 4 every Sunday, enter:
5 4 * * sun /path/to/unixcommand

How do I use operators?

An operator allows you to specifying multiple values in a field. There are three operators:

  1. The asterisk (*) : This operator specifies all possible values for a field. For example, an asterisk in the hour time field would be equivalent to every hour or an asterisk in the month field would be equivalent to every month.
  2. The comma (,) : This operator specifies a list of values, for example: “1,5,10,15,20, 25”.
  3. The dash (-) : This operator specifies a range of values, for example: “5-15” days , which is equivalent to typing “5,6,7,8,9,….,13,14,15” using the comma operator.
  4. The separator (/) : This operator specifies a step value, for example: “0-23/” can be used in the hours field to specify command execution every other hour. Steps are also permitted after an asterisk, so if you want to say every two hours, just use */2.

How do I disable email output?

By default the output of a command or a script (if any produced), will be email to your local email account. To stop receiving email output from crontab you need to append >/dev/null 2>&1. For example:
0 3 * * * /root/backup.sh >/dev/null 2>&1
To mail output to particular email account let us say vivek@nixcraft.in you need to define MAILTO variable as follows:
MAILTO="vivek@nixcraft.in"
0 3 * * * /root/backup.sh >/dev/null 2>&1

See “Disable The Mail Alert By Crontab Command” for more information.

Task: List all your cron jobs

Type the following command:
# crontab -l

crontab -u username -l

To remove or erase all crontab jobs use the following command:
# Delete the current cron jobs #
crontab -r

## Delete job for specific user. Must be run as root user ##
crontab -r -u username

Use special string to save time

Instead of the first five fields, you can use any one of eight special strings. It will not just save your time but it will improve readability.

Special string Meaning
@reboot Run once, at startup.
@yearly Run once a year, “0 0 1 1 *”.
@annually (same as @yearly)
@monthly Run once a month, “0 0 1 * *”.
@weekly Run once a week, “0 0 * * 0”.
@daily Run once a day, “0 0 * * *”.
@midnight (same as @daily)
@hourly Run once an hour, “0 * * * *”.

Examples

Run ntpdate command every hour:
@hourly /path/to/ntpdate
Make a backup everyday:
@daily /path/to/backup/script.sh

More about /etc/crontab file and /etc/cron.d/* directories

/etc/crontab is system crontabs file. Usually only used by root user or daemons to configure system wide jobs. All individual user must must use crontab command to install and edit their jobs as described above. /var/spool/cron/ or /var/cron/tabs/ is directory for personal user crontab files. It must be backup with users home directory.

Understanding Default /etc/crontab

Typical /etc/crontab file entries:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

First, the environment must be defined. If the shell line is omitted, cron will use the default, which is sh. If the PATH variable is omitted, no default will be used and file locations will need to be absolute. If HOME is omitted, cron will use the invoking users home directory.

Additionally, cron reads the files in /etc/cron.d/ directory. Usually system daemon such as sa-update or sysstat places their cronjob here. As a root user or superuser you can use following directories to configure cron jobs. You can directly drop your scripts here. The run-parts command run scripts or programs in a directory via /etc/crontab file:

Directory Description
/etc/cron.d/ Put all scripts here and call them from /etc/crontab file.
/etc/cron.daily/ Run all scripts once a day
/etc/cron.hourly/ Run all scripts once an hour
/etc/cron.monthly/ Run all scripts once a month
/etc/cron.weekly/ Run all scripts once a week

How do I use above directories to put my own scripts or jobs?

Here is a sample shell script called clean.cache. This script is created to clean up cached files every 10 days. This script is directly created at /etc/cron.daliy/ directory. In other words create a text file called /etc/cron.daily/clean.cache as follows.

 #!/bin/bash
# A sample shell script to clean cached file from lighttpd web server
CROOT="/tmp/cachelighttpd/"
 
# Clean files every $DAYS
DAYS=10
 
# Web server username and group name
LUSER="lighttpd"
LGROUP="lighttpd"
 
# Okay, let us start cleaning as per $DAYS
/usr/bin/find ${CROOT} -type f -mtime +${DAYS} | xargs -r /bin/rm
 
# Failsafe 
# if directory deleted by some other script just get it back 
if [ ! -d $CROOT ]
then 
        /bin/mkdir -p $CROOT
        /bin/chown ${LUSER}:${LGROUP} ${CROOT}
fi

Save and close the file. Set the permissions:
# chmod +x /etc/cron.daily/clean.cache

How do I backup installed cron jobs entries?

Simply type the following command to backup your cronjobs to a nas server mounted at /nas01/backup/cron/users.root.bakup directory:
# crontab -l > /nas01/backup/cron/users.root.bakup

crontab -u userName -l > /nas01/backup/cron/users.userName.bakup

What is bashrc file?

.bashrc is a shell script that Bash runs whenever it is started interactively. You can put any command in that file that you could type at the command prompt.

You put commands here to set up the shell for use in your particular environment, or to customize things to your preferences. A common thing to put in .bashrc are aliases that you want to always be available.

.bashrc runs on every interactive shell launch. If you say:

$ bash ; bash ; bash

and then hit Ctrl-D three times, .bashrc will run three times. But if you say this instead:

$ bash -c exit ; bash -c exit ; bash -c exit

then .bashrc won’t run at all, since -c makes the Bash call non-interactive. The same is true when you run a shell script from a file.

Contrast .bash_profile and .profile which are only run at the start of a new login shell. (bash -l) You choose whether a command goes in .bashrc vs .bash_profile depending on on whether you want it to run once or for every interactive shell start.

As a counterexample to aliases, which I prefer to put in .bashrc, you want to do PATH adjustments in .bash_profile instead, since these changes are typically not idempotent:

export PATH="$PATH:/some/addition"

If you put that in .bashrc instead, every time you launched an interactive sub-shell, :/some/addition would get tacked on to the end of the PATH again, creating extra work for the shell when you mistype a command.

You get a new interactive Bash shell whenever you shell out of vi with :sh, for example.

You may view and edit file using the command below.

sudo gedit ~/.bashrc

 

Basic Subdomains in Ruby on Rails

In this article we will cover the basics of using subdomains in Ruby on Rails. Subdomains are quite useful in a number of different scenarios. For example, lets say you are building a multi user blog application. Each user gets their own blog. Being able to give each user a unique subdomain allows you to give users their own personal space. For this article we will build a simple blog application that contains this feature.

Rails Application Setup

The first thing we need to do is generate a couple models. The first model, Blog, represents a specific blog tied to a specific subdomain. A blog contains many posts. The second model, Post, is a simple blog post containing a title and body. Run the commands below to create these models now.

Terminal Commands:
rails g model Blog name subdomain
rails g model Post title body:text blog:references
rake db:migrate

The next thing we need to do is create our controllers. Similarly to the models, we will have a Blogs controller as well as a Posts controller. Run the commands below to create these now.

Terminal Commands:
rails g controller blogs index show
rails g controller posts show

Great, now we need to edit our routes file and set up a few routes. Open up your routes file and modify it so that it looks like the code listed below, being sure not to overwrite the first line of your routes file.

config/routes.rb:
SubdomainsExample::Application.routes.draw do
  resources :posts
  resources :blogs

  match '/', to: 'blogs#index', constraints: { subdomain: 'www' }, via: [:get, :post, :put, :patch, :delete]
  match '/', to: 'blogs#show', constraints: { subdomain: /.+/ }, via: [:get, :post, :put, :patch, :delete]

  root to: "blogs#index"
end

The first two lines are self explanatory. The magic happens on the next 2 lines. The first match line tells rails to match the subdomain ‘www’ to the index method of your blogs controller. This makes it so that typing http://www.yourdomain.com doesn’t search for a subdomain, but rather goes right to the blogs index method. The next match line tells rails to pass the subdomain request onto the blogs/show method.

Next we need to add some code to our application controller. We will add a get_blog method that will find the specific blog by it’s subdomain and return the result. If the blog doesn’t exist the user will be redirected to the blog index. Modify your application controller so that it looks like the code listed below.

app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_filter :get_blog

private
  def get_blog

    blogs = Blog.where(subdomain: request.subdomain)

    if blogs.count > 0
      @blog = blogs.first
    elsif request.subdomain != 'www'
        redirect_to root_url(subdomain: 'www')
    end
  end
end

Excellent, now lets modify our blogs controller. Open up your blogs controller and add in the code listed below.

app/controllers/blogs_controller.rb:
class BlogsController < ApplicationController
  def index
    @blogs = Blog.all
  end

  def show
    @posts = @blog.posts
  end
end


The code above is pretty self explanatory. The index method gets a list of blogs, the show method shows the contents of a specific blog.

Now let’s add some code to our posts controller. Modify your posts controller so that it looks like the code listed below.

app/controllers/posts_controller.rb:
class PostsController < ApplicationController
  def show
    @post = @blog.posts.find(params[:id])
  end
end

This code is pretty simple. It simply grabs the specified post for the current blog.

Now lets do the views. First lets modify our application layout to include bootstrap to make this example pretty. Modify your application layout so that it looks like the code listed below.

app/views/layouts/application.html.erb:
<!DOCTYPE html>
<html>
<head>
  <title>SubdomainsExample</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= stylesheet_link_tag "http://yandex.st/bootstrap/3.0.2/css/bootstrap.min.css", media: "all" %>
  <%= javascript_include_tag "http://yandex.st/bootstrap/3.0.2/js/bootstrap.min.js" %>
  <%= csrf_meta_tags %>
</head>
<body>
class="container"> yield %>
</body> </html>

Great, now lets create our blog index view. Open up your blog index view and modify it so that it looks like the code listed below.

app/views/blogs/index.html.erb:
<h1>Blogs on this Server</h1>

<ul>
    <% @blogs.each do |blog| %>
        <li><%= link_to blog.name, root_url(subdomain: blog.subdomain) %></li>
    <% end %>
</ul>

Okay, now lets update the show view for blogs to look like the code listed below.

app/views/blogs/index.html.erb:
<h1><%= @blog.name %></h1>
<hr />
<% @posts.each do |post| %>

<h3><%= post.title %></h3>
<p><%= truncate post.body, length: 160 %></p>
<%= link_to "Read More", post %>
<% end %>

Great, finally lets modify the show view for posts to look like the code listed below.

app/views/posts/show.html.erb:
<h1><%= @post.title %></h1>
<p>
    <%= @post.body %>
</p>

One final thing. Lets add some seed data. Open up your seeds.rb file and add in the code listed below.

db/seeds.rb:
Blog.delete_all
Blog.create(id: 1, name: "My Example Blog", subdomain: "example")
Blog.create(id: 2, name: "Awesome Blog", subdomain: "awesome")


Post.delete_all
Post.create(id: 1, blog_id: 1, title: "An Example of a Post", body: "This is a perfect example of a blog post.  Feel free to reference this example in your other applications.  Note that the author of this blog post does not accept responsibility for the contents of this blog post.")
Post.create(id: 2, blog_id: 1, title: "Another Example of a Post", body: "This is yet another example of a blog post.  This one is less perfect than the first one.")
Post.create(id: 3, blog_id: 2, title: "An Utterly Awesome Post", body: "This is a super awesome example of a really good blog post.  You should...like...totally copy this!")
Post.create(id: 4, blog_id: 2, title: "Yet Another Utterly Post", body: "This is yet ANOTHER example of a super awesome blog post.  You should totally copy this one as well!")

Now lets run a db:seed to add in the seed data.

Terminal Commands:
rake db:seed

Great, now it’s time to test our application. The easiest way to test on development is to use the vcap.me domain name. vcamp.me and all subdomains point to localhost, so it’s quite simple to test on development. Start a rails server and navigate to localhost:3000. You’ll see a list of blogs. Clicking on one of these blogs will show the specific blog with it’s posts. You can then click on that specific post to display the post. That’s it! Don’t forget to define model association between Blog and Post.

 
 

					

Scan for available WIFI access points on Linux

$sudo iwlist wlan0 scanning | egrep 'Cell |Encryption|Quality|Last beacon|ESSID'

It’s the combination of sudo (run as root, do privileged operations), iwlist wlan0 scanning (produce some output on STDOUT), the pipe symbol “|” (connecting STDOUT of the command(s) to the left to the STDIN of the process on the right), and an egrep command with a “single quoted” (to prevent the shell from interpreting the “|” characters) Regular Expression to filter STDIN. See man bash, man sudo, man iwlist, man egrep, and man re_format for details.

 

Switch back and forth between Wifi and AP on Raspberry Pi

Source: http://sirlagz.net/2013/01/22/script-starting-hostapd-when-wifi-goes-down/

Source: https://www.raspberrypi.org/forums/viewtopic.php?f=26&t=38323

I’ve had issues with my WiFi in the past, and with my Pi running headless it’s sometimes a pain to get it connected back up to WiFi, so I’ve created this little script to start hostapd and dnsmasq whenever the WiFi connection went down, which allowed me to SSH into the Pi even though it wasn’t connected to the network, because it was broadcasting it’s own network !

This can be customised to do different things if either WiFi or ethernet go down.


#!/bin/bash
#
# Interface checker
# Checks to see whether interface has an IP address, if it doesn't assume it's down and start hostapd
# Author : SirLagz
#
Interface='wlan0'
HostAPDIP='10.0.0.1'
echo "-----------------------------------"
echo "Checking connectivity of $Interface"
NetworkUp=`/sbin/ifconfig $Interface`
IP=`echo "$NetworkUp" | grep inet | wc -l`
if [[ $IP -eq 0 ]]; then
echo "Connection is down"


hostapd=`pidof hostapd`
if [[ -z $hostapd ]]; then
# If there are any more actions required when the interface goes down, add them here
echo "Attempting to start hostapd"
/etc/init.d/hostapd start
echo "Attempting to start dnsmasq"
/etc/init.d/dnsmasq start
echo "Setting IP Address for wlan0"
/sbin/ifconfig wlan0 $HostAPDIP netmask 255.255.255.0 up
fi
elif [[ $IP -eq 1 && $NetworkUp =~ $HostAPDIP ]]; then
echo "IP is $HostAPDIP - hostapd is running"
else
echo "Connection is up"
hostapd=`pidof hostapd`
if [[ ! -z $hostapd ]]; then
echo "Attempting to stop hostapd"
/etc/init.d/hostapd stop
echo "Attempting to stop dnsmasq"
/etc/init.d/dnsmasq stop
echo "Renewing IP Address for $Interface"
/sbin/dhclient wlan0
fi
fi
echo "-----------------------------------"