Writing Shell Scripts Under Unix

Một phần của tài liệu thư viện số dau mysql cookbook (Trang 69 - 72)

Chapter 1. Using the mysql Client Program

1.33 Using mysql in Shell Scripts

1.33.4 Writing Shell Scripts Under Unix

Here is a shell script that reports the current uptime of the MySQL server. It runs a SHOW STATUS query to get the value of the Uptime status variable that contains the server uptime in seconds:

#! /bin/sh

# mysql_uptime.sh - report server uptime in seconds mysql -B -N -e "SHOW STATUS LIKE 'Uptime'"

The first line of the script that begins with #! is special. It indicates the pathname of the program that should be invoked to execute the rest of the script, /bin/sh in this case. To use the script, create a file named mysql_uptime.sh that contains the preceding lines and make it executable with chmod +x. The mysql_uptime.sh script runs mysql using -e to indicate the query string, -B to generate batch (tab-delimited) output, and -N to suppress the column header line. The resulting output looks like this:

% ./mysql_uptime.sh Uptime 1260142

The command shown here begins with ./, indicating that the script is located in your current directory. If you move the script to a directory named in your PATH setting, you can invoke it from anywhere, but then you should omit the ./ from the command. Note that moving the script make cause csh or tcsh not to know where the script is located until your next login. To remedy this without logging in again, use rehash after moving the script. The following example illustrates this process:

% ./mysql_uptime.sh Uptime 1260348

% mv mysql_uptime.sh /usr/local/bin

% mysql_uptime.sh

mysql_uptime.sh: Command not found.

% rehash

% mysql_uptime.sh Uptime 1260397

If you prefer a report that lists the time in days, hours, minutes, and seconds rather than just seconds, you can use the output from the mysql STATUS statement, which provides the following information:

mysql> STATUS;

Connection id: 12347 Current database: cookbook

Current user: cbuser@localhost Current pager: stdout

Using outfile: ''

Server version: 3.23.47-log Protocol version: 10

Connection: Localhost via UNIX socket Client characterset: latin1

Server characterset: latin1

UNIX socket: /tmp/mysql.sock

Uptime: 14 days 14 hours 2 min 46 sec

For uptime reporting, the only relevant part of that information is the line that begins with Uptime. It's a simple matter to write a script that sends a STATUS command to the server and filters the output with grep to extract the desired line:

#! /bin/sh

# mysql_uptime2.sh - report server uptime

mysql -e STATUS | grep "^Uptime"

The result looks like this:

% ./mysql_uptime2.sh

Uptime: 14 days 14 hours 2 min 46 sec

The preceding two scripts specify the statement to be executed by means of the -e command- line option, but you can use other mysql input sources described earlier in the chapter, such as files and pipes. For example, the following mysql_uptime3.sh script is like

mysql_uptime2.sh but provides input to mysql using a pipe:

#! /bin/sh

# mysql_uptime3.sh - report server uptime echo STATUS | mysql | grep "^Uptime"

Some shells support the concept of a "here-document," which serves essentially the same purpose as file input to a command, except that no explicit filename is involved. (In other words, the document is located "right here" in the script, not stored in an external file.) To provide input to a command using a here-document, use the following syntax:

command <<MARKER input line 1 input line 2 input line 3 ...

MARKER

<<MARKER signals the beginning of the input and indicates the marker symbol to look for at the end of the input. The symbol that you use for MARKER is relatively arbitrary, but should be some distinctive identifier that does not occur in the input given to the command.

Here-documents are a useful alternative to the -e option when you need to specify lengthy query input. In such cases, when -e becomes awkward to use, a here-document is more convenient and easier to write. Suppose you have a log table log_tbl that contains a column date_added to indicate when each row was added. A query to report the number of records that were added yesterday looks like this:

SELECT COUNT(*) As 'New log entries:' FROM log_tbl

WHERE date_added = DATE_SUB(CURDATE( ),INTERVAL 1 DAY);

That query could be specified in a script using -e, but the command line would be difficult to read because the query is so long. A here-document is a more suitable choice in this case because you can write the query in more readable form:

#! /bin/sh

# new_log_entries.sh - count yesterday's log entries

mysql cookbook <<MYSQL_INPUT

SELECT COUNT(*) As 'New log entries:' FROM log_tbl

WHERE date_added = DATE_SUB(CURDATE( ),INTERVAL 1 DAY);

MYSQL_INPUT

When you use -e or here-documents, you can refer to shell variables within the query input—

although the following example demonstrates that it might be best to avoid the practice.

Suppose you have a simple script count_rows.sh for counting the rows of any table in the cookbook database:

#! /bin/sh

# count_rows.sh - count rows in cookbook database table

# require one argument on the command line if [ $# -ne 1 ]; then

echo "Usage: count_rows.sh tbl_name";

exit 1;

fi

# use argument ($1) in the query string mysql cookbook <<MYSQL_INPUT

SELECT COUNT(*) AS 'Rows in table:' FROM $1;

MYSQL_INPUT

The script uses the $# shell variable, which holds the command-line argument count, and $1, which holds the first argument after the script name. count_rows.sh makes sure that exactly one argument was provided, then uses it as a table name in a row-counting query. To run the script, invoke it with a table name argument:

% ./count_rows.sh limbs Rows in table:

12

Variable substitution can be helpful for constructing queries, but you should use this capability with caution. A malicious user could invoke the script as follows:

% ./count_rows.sh "limbs;DROP TABLE limbs"

In that case, the resulting query input to mysql becomes:

SELECT COUNT(*) AS 'Rows in table:' FROM limbs;DROP TABLE limbs;

This input counts the table rows, then destroys the table! For this reason, it may be prudent to limit use of variable substitution to your own private scripts. Alternatively, rewrite the script using an API that allows special characters such as ; to be dealt with and rendered harmless (see Recipe 2.8).

Một phần của tài liệu thư viện số dau mysql cookbook (Trang 69 - 72)

Tải bản đầy đủ (PDF)

(1.068 trang)