Category Archives: Bash

Prevent SSH connection from timing out in Terminal

If you’re constantly connected to multiple servers via SSH and perform work on them throughout the day, dealing with timeouts can be cumbersome. Here’s how you can keep the connection alive.

Create a config file in your home’s .ssh directory:

1
$ vi ~/.ssh/config
$ vi ~/.ssh/config

Add the following by pressing the letter i, typing in the text below, and pressing ESC followed by :wq:

1
ServerAliveInterval 60
ServerAliveInterval 60

Every 60 seconds a packet will be sent to keep the connection alive.

Lastly, modify the config file so that it’s read-only to you:

1
$ chmod 600 ~/.ssh/config
$ chmod 600 ~/.ssh/config

From here on out, no more timeouts.

Managing file and folder permissions when deploying with Git

Preface

I use Git as a version control and deployment system. When a website gets pushed to a server, all files get pulled into the web root (i.e. htdocs) by a user named git executing git pull in the post-receive hook.

By default, all files and folders git creates have 664 and 775 permissions, respectively, and are owned by that user. 664 translates to the user and group being able to read and write, and everyone else only being able to read, and 775 translates to the user and group being able to read, write and execute, and everyone else only being able to read and execute. (That’s a mouthful!)

1
2
-rw-rw-r-- 1 git  git   30 Aug  15  23:04 test-file.txt
drwxrwxr-x 1 git  git  102 Aug  15  23:04 test-directory
-rw-rw-r-- 1 git  git   30 Aug  15  23:04 test-file.txt
drwxrwxr-x 1 git  git  102 Aug  15  23:04 test-directory

Now, in an instance where you need a folder in htdocs writable by another user, like apache, for let’s say a caching system, you need to be able to set those particular permissions accordingly.

To accomplish this, you really only have two options:

  1. Set permissions of files to 666 and folders to 777
  2. Set the owner or group to apache (or a group that apache is a member of)

Personally, I favor restrictive permissions over convenience, so option #1 is out, which means we’re going to take a look at how to implement option #2.

Continue reading

WordPress cron not executing scheduled events

I recently tried to schedule an event to be executed twice daily in WordPress MU 3.5 via the wp_schedule_event function, but for some reason the event never fired. I confirmed that the event was indeed scheduled properly, but when reviewing the timestamp of the event via wp_next_scheduled, it continued to return the timestamp of when I first scheduled it, indicating that it never executed.

After some testing and with the help of the Cron View plugin, which shows you a complete schedule of all crons, I’ve come to realize that not even core WordPress events were being executed, pointing to a more global problem. The most import information I gathered from this plugin was that all core WordPress events stopped firing on the same day, which means something affected it right around that time.

Eventually I remembered that I protected the WordPress installation with an Apache basic auth the day before. It prevented the WordPress cron from running because it didn’t have the proper credentials to proceed.

A simple fix for this was to exclude the WordPress cron from needing authentication, which can be accomplished with the following few lines in your virtual host or htaccess file:

1
2
3
<FilesMatch "(wp-cron\.php)$">
    Allow from all
</FilesMatch>
<FilesMatch "(wp-cron\.php)$">
    Allow from all
</FilesMatch>

Since this WordPress installation is only running in a staging environment, that piece of code was sufficient, but if this is your production environment, take a look at other possible file exclusions.

Last but not least, even though my cron was admin specific, placing the action within the admin_init hook didn’t not work, so keep in mind that it must used within init.

Using the HTML5 video player for serving .ogv files in Firefox and Safari, and .mp4 files in Internet Explorer

I was working with a web page that used the following code to embed videos:

1
2
3
<video width="320" height="240" controls>
   <source src="videos/demo.ogv" type="video/ogg">
</video>
<video width="320" height="240" controls>
   <source src="videos/demo.ogv" type="video/ogg">
</video>

But they weren’t playing in Firefox, Safari or Internet Explorer — only Chrome.

Let’s break down the issues I encountered with each browser and how I solved them.

Issues with Safari

The problem with Safari was that the website was protected with Apache’s basic authentication:

1
2
3
4
AuthType Basic
AuthName "Password Protected"
AuthUserFile /var/www/domain.com/htdocs/.htpasswd
Require valid-user
AuthType Basic
AuthName "Password Protected"
AuthUserFile /var/www/domain.com/htdocs/.htpasswd
Require valid-user

To work around that issue, I moved the videos outside of the protected directory. I did this by reusing a virtual host I created a while back for assets i.e. assets.domain.com. Once I moved the videos and updated the HTML5 code:

1
2
3
<video width="320" height="240" controls>
   <source src="http://assets.domain.com/videos/demo.ogv" type="video/ogg">
</video>
<video width="320" height="240" controls>
   <source src="http://assets.domain.com/videos/demo.ogv" type="video/ogg">
</video>

The videos played fine in Safari and Chrome.

Issues with Firefox

The problem with Firefox was the following error:

No video with supported format and MIME type found.

A quick search revealed that it was in fact because of a missing MIME type. To test this, I placed a .htaccess file in the web root with the following command in it:

1
AddType video/ogg .ogv
AddType video/ogg .ogv

But it didn’t work. Then I realized that I wasn’t serving the videos from domain.com, but rather, assets.domain.com. So I placed the .htaccess file in the web root of assets.domain.com and now the videos also played in Firefox.

As a side note, if you’ll be serving such files across multiple websites on your server, you should consider adding the MIME at the server level.

Issues with Internet Explorer

Internet Explorer displayed absolutely nothing (not even a video box with an X — more on that later). Turns out, IE9 or less does not support .ogv files. You’ll need an .mp4 version of your videos. Luckily, I was provided with those, so I modified the embed code to:

1
2
3
4
<video width="320" height="240" controls>
   <source src="http://assets.domain.com/videos/demo.ogv" type="video/ogg">
   <source src="http://assets.domain.com/videos/demo.mp4" type="video/mp4">
</video>
<video width="320" height="240" controls>
   <source src="http://assets.domain.com/videos/demo.ogv" type="video/ogg">
   <source src="http://assets.domain.com/videos/demo.mp4" type="video/mp4">
</video>

You should also double check that you have the following MIME type already setup:

1
AddType video/mp4 .mp4
AddType video/mp4 .mp4

Next I noticed that only one video played. Another quick search online revealed that those videos must use the H.264 codec. Unfortunately, only one of them used it; the others were MPEG-4.

You can easily find out what codec you’re using if you’re on a Mac:

  • Right-click on the video.
  • Choose Get Info.
  • Expand More Info.
  • Look under Codecs.

While I was doing this research, I found a neat way to troubleshoot those videos in Internet Explorer.

If you’re on the page with the broken videos:

  • Open Internet Explorer’s developer tools (F12).
  • Click on the Console tab.
  • Type in the following and hit ENTER:
    document.getElementsByTagName("video")[0].error.code
  • If the first video on the page is not the video you’re having problems with, increment the index.
  • Visit this page for error code details.

That’s it. Once you get your videos converted, you should be good to go.

Issues with testing from a corporate network

In my instance, I was performing these tests from a corporate network. Turns out, all websites were automatically served in compatibility view, meaning that even though the one video had the right codec, it wasn’t playing. This is also why the video box was blank as apposed to showing an X.

I noticed that because of a message in developer tools:

HTML1202: http://domain.com is running in Compatibility View because ‘Display intranet sites in Compatibility View’ is checked.

That was a tricky one, because I almost didn’t see that. The way you can try to get around that is as follows:

  • Click on the settings gear toward the top right.
  • Choose Internet options.
  • Click on the Security tab.
  • Click on the Local intranet icon.
  • Click on the Sites button.
  • Click on the Advanced button.
  • Select the appropriate website and click Remove.
  • Don’t forget to put that entry back later 😉

I should point out that your changes may not be saved, depending on the network policy. It’s also a very good idea to check with your help desk, since this is a legitimate requirement, and therefore they may be able to offer an alternative such as creating a local computer account.

If you have any questions about any of the troubleshooting steps I wrote about, feel free to ask in the comments below.

Permanently share a folder between host (Mac) and guest (Linux) OS using VirtualBox

This is mainly for my own reference, but here it goes.

1. Share a folder on the host OS

  • In VirtualBox, click your OS on the left and click on Settings.
  • Click on the Shared Folders tab.
  • Click on the folder with the plus on the right.
  • Browse to a folder of your choice in the folder path.
  • Enter a folder name with no spaces e.g. “Share”.
  • Check Auto-mount and Make Permanent, if available.
  • Click on OK.

2. Mount the folder in the guest OS

  • Create a folder in your guest OS that you want to share.
  • Open up Terminal.
  • Type in id and press ENTER— remember that ID.
  • Switch to the root user using sudo su and enter your password.
  • Browse to the etc folder using cd /etc.
  • Edit the rc.local file using vi rc.local.
  • Move your cursor right above exit 0 and press the letter “i” on your keyboard to insert text.
  • Type in the following: sudo mount -t vboxsf -o uid=1000,gid=1000 Share /home/username/Documents/Share
    • 1000 should match the ID you noted down earlier.
    • Share should match the folder name from step 1.
    • username should match your Linux username.
    • /Documents/Share should be the absolute path of the new folder you created.
  • Now hit “ESC”, type :wq and hit ENTER to save and quit the file editing.

After you restart the guest OS, your shared folder will be automatically mounted.