Browse Category: tips and tricks

Über-simple generic RHEL/CentOS init script

Fill in the indicated bits, drop in /etc/rc.d/init.d/ , chmod +x, and away you go!

#!/bin/bash
# chkconfig: 2345 90 90
# description: program_name
### BEGIN INIT INFO
# Provides: program_name
# Required-Start: network
# Required-Stop: network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Start the program
### END INIT INFO

### Fill in these bits:
START_CMD="java -jar /home/kale/bin/program_name.jar > /var/log/program_name/program_name.log 2>&1 &"
NAME="program_name"
PGREP_STRING="/home/kale/bin/program_name.jar"
PID_FILE="/var/run/program_name/program_name.pid"
USER="username"

### No further muckin' about needed!

CUR_USER=`whoami`

killproc() {
  pkill -u $USER -f $PGREP_STRING
}

start_daemon() {
  eval "$*"
}

log_success_msg() {
  echo "$*"
  logger "$_"
}

log_failure_msg() {
  echo "$*"
  logger "$_"
}

check_proc() {
  pgrep -u $USER -f $PGREP_STRING >/dev/null
}

start_script() {
  if [ "${CUR_USER}" != "root" ] ; then
    log_failure_msg "$NAME can only be started as 'root'."
    exit -1
  fi

  check_proc
  if [ $? -eq 0 ]; then
    log_success_msg "$NAME is already running."
    exit 0
  fi

  [ -d /var/run/$NAME ] || (mkdir /var/run/$NAME )

   # make go now 
    start_daemon /bin/su $USER -c "$START_CMD"

  # Sleep for a while to see if anything cries
  sleep 5
  check_proc

  if [ $? -eq 0 ]; then
    log_success_msg "Started $NAME."
  else
    log_failure_msg "Error starting $NAME."
    exit -1
  fi
}

stop_script() {
  if [ "${CUR_USER}" != "root" ] ; then
    log_failure_msg "You do not have permission to stop $NAME."
    exit -1
  fi

  check_proc
  if [ $? -eq 0 ]; then
    killproc -p $PID_FILE >/dev/null

    # Make sure it's dead before we return
    until [ $? -ne 0 ]; do
      sleep 1
      check_proc
    done

    check_proc
    if [ $? -eq 0 ]; then
      log_failure_msg "Error stopping $NAME."
      exit -1
    else
      log_success_msg "Stopped $NAME."
    fi
  else
    log_failure_msg "$NAME is not running or you don't have permission to stop it"
  fi
}

check_status() {
  check_proc
  if [ $? -eq 0 ]; then
    log_success_msg "$NAME is running."
  else
    log_failure_msg "$NAME is stopped."
    exit -1
  fi
}

case "$1" in
  start)
    start_script
    ;;
  stop)
    stop_script
    ;;
  restart)
    stop_script
    start_script
    ;;
  status)
    check_status
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
esac

exit 0

bash, /dev/net and you

found during a random goog search on Dave Smith’s Blog:

exec 3<>/dev/tcp/www.google.com/80
echo -e "GET / HTTP/1.1\n\n" >&3
cat <&3

seriously, wrap your head around that. /dev/net isn't a real device, it's a magical pseudodevice that bash intercepts and opens a socket as requested.

Enforcing Secure Passwords in Horde

A coworker, Alex, discovered that Horde, in conjunction with Plesk, allows users to change their passwords arbitrarily — but doesn’t enforce any sort of password policy, allowing such passwords as “test” or even “” (null). This, obviously, is a huge security risk as mail compromises can lead to fairly terrible things.

From his article:

If you (or a client you are representing) want to set horde to do the typical “strict password” enforcement, look for the file:

horde/passwd/backends.php

And read the bit about password policy. An example policy that can be set in this file that would require 1 capital, 1 lowercase, 1 special character and 1 number, with a minimum password size of 8, would look like:

‘password policy’ => array(
‘minLength’ => 8,
‘maxLength’ => 64,
‘maxSpace’ => 0,
‘minUpper’ => 1,
‘minLower’ => 1,
‘minNumeric’ => 1,
‘minSymbols’ => 1
),

Can’t fork?

Can’t fork but need to see what’s going on? Hint: a box that can’t fork can often `exec’.

Here are a pair of slick bash functions that can be lifesavers in dire situations:

`ls’:

$ myls() { while [ $# -ne 0 ] ; do echo "$1" ; shift ; done ; }
$ myls /etc/s*
/etc/services
/etc/shells
/etc/syslog.conf

`cat’:

$ mycat() { while IFS="" read l ; do echo "$l" ; done < $1 ; }
$ mycat /etc/shells

Log PHP memory usage per-request

You can easily log how much memory each request for a PHP page takes by modifying the LogFormat:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b %{mod_php_memory_usage}n \"%{Referer}i\" \"%{User-Agent}i\"" combined-php

Note the latter definition, which includes %{mod_php_memory_usage}n — this will print out the amount of memory, in bytes, required to execute the script as requested. Big help in finding memory leaks. To use, just change the log definition to the newly-created “combined-php” format:

CustomLog logs/fever-access_log combined-php

Do note that this may (probably will) break Apache log parsers that are expecting the standard combined format. If using for troubleshooting, I recommend logging to an alternate location so as to not screw up log statistics.

Credit to Brad Ison for this find

Easier-to-read MySQL “show table status”

[code lang=”bash”]mysqlshow –status db_name |sort -n -k10 |awk -F\| ‘($6 !~ /0/)’ |awk -F\| ‘{print $2 ” ” $6 ” ” $7 ” ” $14}’ |egrep -v “^ “[/code]

Creates a much easier-to-read view of the output of “show table status”:

Name                    Rows   Avg_row_length   Update_time         
 wp_users                1      140              2009-08-08 04:13:07 
 wp_links                9      106              2009-10-16 12:57:32 
 wp_comments             14     464              2009-11-28 16:09:43 
 wp_usermeta             15     166              2009-11-29 06:41:19 
 wp_term_taxonomy        53     40               2009-11-20 14:06:21 
 wp_postmeta             141    46               2009-11-29 06:44:05 
 wp_options              172    4624             2009-11-29 06:40:59 
 wp_term_relationships   357    21               2009-11-21 02:35:42 

Greasemonkey script to make Youtube better

I hacked up a Greasemonkey script tonight to address my very real problem with Youtube: Flash.

I use a Macbook Air and dearly love it, though I’m rather cognizant of the fact that it’s powered by a dying hamster. Playing a video in Youtube will inevitably stutter or cause my lap to catch fire, both undesirable. There are also advertisements and Flash sucks up memory and CPU like crazy.

I attempted to address a different issue before arriving at this solution, namely, Youtube’s new throttling algorithm by. I realized, however, that I’m simply not smart enough to figure that puzzle out, though I learned quite a bit about HTML5 and its <video> tag along the way.

I’d like to point out first that I’m not a JavaScript coder — I’ve actually never used it until tonight, so please don’t judge too harshly. This Greasemonkey script is a mishmash of about 3 other Greasemonkey scripts and some regexes I used in a PHP script.

Install Youtube Flash-No-Mo

Do note that while the script works like a champ on Safari and Chrome (and likely any other webkit-based browser), Firefox 3.5 does not have a built-in handler for mp4 content. You may need to install an additional plugin (mplayer maybe?) to get things to work right on Firefox.

PHP, eval, and HTTP response codes

The PHP eval() function is an odd beast. I’ve encountered this a few times before, wherein a site will display just fine, but Google won’t index it, and if you review the headers for the page (using curl or telnet), you’ll see that instead of the expected 200 OK response, you’ll get a “HTTP/1.0 500 Internal Server Error” — bad juju for all of your hard SEO work.

Taking a look at the site’s error_log may reveal a PHP error — often a syntax error or some such. However, the line of code to which it refers is just an eval() statement for an included file.

If the eval’d code has an error, the code running the eval statement will work just fine; however, because of the error in the eval’d code, the response code header will return a 500. This, interestingly enough, will only occur if display_errors is set to off.

The ideal solution is to fix the code that is being eval’d.

The hackish way, which I prefer because I’m lazy, is to do something terrible such as:

[code lang=”PHP”]// There’s got to be a better way to do this.
ini_set(“display_errors”, “on”);
eval($code);
ini_set(“display_errors”, “off”);
[/code]

The response code will now be 200 and Google will be happy; however, the problem isn’t *really* solved…

Save a file in vi as the superuser

If you’ve opened a file in vi for which you don’t have write privileges, you can save the file as the superuser (if your user is in the sudoers list) by running the following vi command:

[code]:w !sudo tee %[/code]

After doing so, vi will detect that the file has changed and ask if you want to reload it.

Sort based on a column

You can use the `sort’ utility to sort not only on the first field, but also an arbitrary column. Take this output from ps:

[code lang=”bash”][kale@superhappykittymeow ~]$ ps ax -ly |grep httpd
R 502 10027 8387 0 78 0 668 979 – pts/1 0:00 grep httpd
S 502 10247 28321 0 76 0 16924 9961 semtim ? 1:58 /usr/sbin/httpd
S 0 28321 1 0 78 0 11564 7645 – ? 0:00 /usr/sbin/httpd
S 502 28327 28321 0 75 0 19152 10412 semtim ? 1:39 /usr/sbin/httpd
S 502 28328 28321 0 84 0 16628 9903 semtim ? 1:56 /usr/sbin/httpd
S 502 28331 28321 0 75 0 17108 9962 semtim ? 1:45 /usr/sbin/httpd
S 502 28332 28321 0 75 0 19152 10446 semtim ? 1:54 /usr/sbin/httpd
S 502 28333 28321 0 75 0 15692 9624 semtim ? 1:54 /usr/sbin/httpd
S 502 28334 28321 0 78 0 17476 10107 semtim ? 2:01 /usr/sbin/httpd
S 502 28335 28321 0 75 0 17460 10237 semtim ? 1:57 /usr/sbin/httpd
S 502 28336 28321 0 75 0 16836 9897 – ? 1:54 /usr/sbin/httpd
S 502 30058 28321 0 75 0 15248 9622 semtim ? 0:33 /usr/sbin/httpd
[/code]

This can be sorted by the SZ column, column 9, as such:

[code lang=”bash”][kale@superhappykittymeow ~]$ ps ax -ly |grep httpd |sort -nr -k 9n
R 502 10045 8387 0 78 0 668 979 – pts/1 0:00 grep httpd
S 0 28321 1 0 78 0 11564 7645 – ? 0:00 /usr/sbin/httpd
S 502 30058 28321 0 75 0 15248 9622 semtim ? 0:33 /usr/sbin/httpd
S 502 28333 28321 0 75 0 15692 9624 semtim ? 1:54 /usr/sbin/httpd
S 502 28336 28321 0 75 0 16836 9897 – ? 1:54 /usr/sbin/httpd
S 502 28328 28321 0 84 0 16628 9903 semtim ? 1:56 /usr/sbin/httpd
S 502 10247 28321 0 76 0 16924 9961 semtim ? 1:58 /usr/sbin/httpd
S 502 28331 28321 0 75 0 17108 9962 semtim ? 1:45 /usr/sbin/httpd
S 502 28334 28321 0 78 0 17476 10107 semtim ? 2:01 /usr/sbin/httpd
S 502 28335 28321 0 75 0 17460 10237 semtim ? 1:57 /usr/sbin/httpd
S 502 28327 28321 0 75 0 19152 10412 semtim ? 1:39 /usr/sbin/httpd
S 502 28332 28321 0 75 0 19152 10446 semtim ? 1:54 /usr/sbin/httpd
[/code]

The -k switch tells sort to sort based on a key, which we specify as 9n (column 9, numeric). Much easier to review the output.

Extend bash functionality

[code lang=”bash”]# make bash autocomplete with up arrow
bind ‘”\e[A”:history-search-backward’
bind ‘”\e[B”:history-search-forward’

# make tab cycle through commands instead of listing
bind ‘”\t”:menu-complete'[/code]

Curl with postdata and cookies

Great for command-line logging into sites to pull content for whatever reason.

[code lang=”bash”]curl -c cookies.txt -d “username=username&password=password&action=login” -o /home/kale/outputfile.txt “http://www.domain.com/authenticated_page.php?foo=bar”[/code]

Of course, you’ll have to look at the source for the target location’s login page to see what variables it wants. I use it to grab a single Cacti-generated graph that is normally password protected, but I want to include a single graph on another site, so I cron’d a script to run a line similar to the above to log in and save it locally.

  • 1
  • 2