blob: c7975d5e5fd3cf2d594997ac444c1e375b685a01 [file] [log] [blame]
Yu-Ju Hongb652f0f2012-08-20 11:42:42 -07001#!/bin/bash
2
3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# This script creates a CPU set and binds the MySQL process to the
8# set. It restarts MySQL if specified in the option. This script needs
9# to be run with "sudo".
10
11set -e # Exit if any function returns a non-zero value.
12set -o nounset # Exit if any variable is used unset.
13
14MYSQL_PATH='/etc/init.d/mysql.server'
15MYSQL_PID_PATH='/var/lib/mysql/atlantis1.mtv.corp.google.com.pid'
16MYSQL_PROC_NAME='mysqld'
17
18# The directory where we mount the cpuset virutal file system to.
19MOUNT_DIR='/dev/cpuset'
20# The base cpuset directory for mysql.
21MYSQL_CPUSET='mysql'
22# CPUs in MySQL cpuset. E.g. 0-2,7,12-14.
23MYSQL_DEFAULT_CPUS=10-15
24
25
26# Display usage.
27function usage() {
28 echo -e "Usage: $0 [-c <CPUs>] [-p <PID>] [-r] [-d]\n"
29 echo -e "Create and bind the MySQL process to a specified CPU set.\n"
30 echo -e "Options:"
31 echo -e " -c <CPUs> Specify a list of CPUs to be used. E.g. 0-2,7,12-14"
32 echo -e " (Default: $MYSQL_DEFAULT_CPUS)."
33 echo -e " -d Delete the CPU set. This option kills the current"
34 echo -e " MySQL process and delete the CPU set. It does not"
35 echo -e " restart MySQL nor create a new CPU set. (Default:"
36 echo -e " disabled)."
37 echo -e " -p <PID> Bind <PID> to the cpuset (Default: the script searches"
38 echo -e " for the MySQL PID automatically)."
39 echo -e " -r Restart MySQL (Default: disabled)."
40 echo -e " -h Display this usage information."
41 echo -e "\n"
42}
43
44function print_info() {
45 msg=$1
46 echo "INFO: "$msg
47}
48
49function print_error() {
50 msg=$1
51 echo "ERROR: "$msg
52}
53
54# Run and print out the command if the silent flag is not set (the default).
55# Usage: run_cmd <cmd> [slient]
56function run_cmd() {
57 cmd=""
58 slient=0
59
60 if [ $# -gt 0 ]; then
61 cmd=$1
62 else
63 print_error "Empty command!"
64 return 1
65 fi
66
67 if [ $# -gt 1 ]; then
68 silent=$2
69 fi
70
71 if [ $slient -eq 0 ]; then
72 print_info "Running \"${1}\""
73 fi
74
75 # Print an error message if the command failed.
76 eval "$1" || { print_error "Failed to execute \"${cmd}\""; return 1; }
77}
78
79# Get the PID of the MySQL.
80function get_mysql_pid() {
81 local pid=""
82
Yu-Ju Hongc63cc632012-08-30 09:57:26 -070083 if [ $# -gt 0 ] && [ ! -z "$1" ]; then
Yu-Ju Hongb652f0f2012-08-20 11:42:42 -070084 # Use user-provided PID.
85 pid=$1
86 elif [ ! -z ${MYSQL_PID_PATH} -a -f ${MYSQL_PID_PATH} ]; then
87 # Get PID from MySQL PID file if it is set.
88 print_info "Getting MySQL PID from ${MYSQL_PID_PATH}..."
89 pid=$(cat $MYSQL_PID_PATH) || \
90 { print_error "No MySQL process found."; return 1; }
91 else
92 # Get PID of process named mysqld.
93 print_info "Searching for MySQL PID..."
94 # Ignore the return code to print out an error message.
95 pid=$(pidof $MYSQL_PROC_NAME) || \
96 { print_error "No MySQL process found."; return 1; }
97 fi
98
99 # Test if the PID is an integer
100 if [[ $pid != [0-9]* ]]; then
101 print_error "No MySQL process found."
102 return 1
103 fi
104
105 # Check if the PID is a running process.
106 if [ ! -d "/proc/${pid}" ]; then
107 print_error "No running MySQL process is found."
108 return 1
109 fi
110
111 _RET="$pid"
112 print_info "MySQL PID is ${pid}."
113}
114
115# Mount the cpuset virtual file system.
116function mount_cpuset() {
117 if (mount | grep "on ${MOUNT_DIR} type" > /dev/null)
118 then
119 print_info "${MOUNT_DIR} already mounted."
120 else
121 print_info "Mounting cpuset to $MOUNT_DIR."
122 run_cmd "mkdir -p ${MOUNT_DIR}"
123 run_cmd "mount -t cpuset none ${MOUNT_DIR}"
124 fi
125}
126
127
128function clean_all() {
129 local delete_msg="No"
130 print_info "Will Delete existing CPU set..."
131 echo -ne "WARNING: This operation will kill all running "
132 echo "processes in the CPU set."
133 echo -ne "Are you sure you want to proceed "
134 echo -ne "(type \"yes\" or \"Yes\" to proceed)? "
135 read delete_msg
136
137 mount_cpuset
138
139 local proc_list=""
140 local proc=""
141
142 if [ "$delete_msg" = "yes" -o "$delete_msg" = "Yes" ]; then
143 if [ -d "${MOUNT_DIR}/${MYSQL_CPUSET}" ]; then
144 proc_list=$(cat ${MOUNT_DIR}/${MYSQL_CPUSET}/cgroup.procs)
145 for proc in $proc_list; do
146 run_cmd "kill -9 ${proc}"
147 done
148 # Remove the CPU set directory.
149 run_cmd "rmdir ${MOUNT_DIR}/${MYSQL_CPUSET}"
150 # Unmount the cpuset virtual file system.
151 run_cmd "umount ${MOUNT_DIR}"
152 else
153 print_info "The CPU set does not exist."
154 return 1
155 fi
156 print_info "Done!"
157 else
158 # User does not wish to continue.
159 print_info "Aborting program."
160 fi
161}
162
163
164function main() {
165
166 local MYSQL_CPUS=$MYSQL_DEFAULT_CPUS
167 local RESTART_MYSQL_FLAG=0
168 local DELETE_CPUSET_FLAG=0
169 local MYSQL_PID=""
170
171 # Parse command-line arguments.
172 while getopts ":c:dhp:r" opt; do
173 case $opt in
174 c)
175 MYSQL_CPUS=$OPTARG
176 ;;
177 d)
178 DELETE_CPUSET_FLAG=1
179 ;;
180 h)
181 usage
182 return 0
183 ;;
184 p)
185 MYSQL_PID=$OPTARG
186 ;;
187 r)
188 RESTART_MYSQL_FLAG=1
189 ;;
190 \?)
191 echo "Invalid option: -$OPTARG" >&2
192 usage
193 return 1
194 ;;
195 :)
196 echo "Option -$OPTARG requires an argument." >&2
197 usage
198 return 1
199 ;;
200 esac
201 done
202
203
204 # Clean up and exit if the flag is set.
205 if [ $DELETE_CPUSET_FLAG -eq 1 ]; then
206 clean_all
207 return 0
208 fi
209
210 # Restart MySQL.
211 if [ $RESTART_MYSQL_FLAG -eq 1 ]; then
212 print_info "Restarting MySQL..."
213 $MYSQL_PATH restart
214 fi
215
216
217 # Get PID of MySQL.
218 get_mysql_pid "$MYSQL_PID"
219 MYSQL_PID=$_RET
220
221 mount_cpuset
222
223 # Make directory for MySql.
224 print_info "Making a cpuset for MySQL..."
225 run_cmd "mkdir -p ${MOUNT_DIR}/${MYSQL_CPUSET}"
226
227 # Change working directory.
228 run_cmd "cd ${MOUNT_DIR}/${MYSQL_CPUSET}"
229
230 # Update the CPUs to use in the CPU set. Note that we use /bin/echo
231 # explicitly (instead of "echo") because it displays write errors.
232 print_info "Updating CPUs in the cpuset..."
233 run_cmd "bash -c \"/bin/echo ${MYSQL_CPUS} > cpus\""
234
235 # Attach/Rebind MySQL process to the cpuset. Note that this command
236 # can only attach one PID at a time. This needs to be run every time
237 # after the CPU set is modified.
238 print_info "Bind MySQL process to the cpuset..."
239 run_cmd "bash -c \"/bin/echo ${MYSQL_PID} > tasks\""
240
241 print_info "Done!"
242}
243
244main "$@"