系统脚本实用指南:进程优先级调整、虚拟主机添加与Mac OS X优化
1. 按进程名调整任务优先级
在系统运行过程中,有时需要调整特定任务的优先级。例如,IRC或聊天服务器应仅使用“空闲”周期,MP3播放器应用或文件下载变得不那么重要,或者需要提高实时CPU监视器的优先级。然而,
renice
命令需要指定进程ID,这可能比较麻烦。更实用的方法是编写一个脚本,将进程名映射到进程ID,然后调整指定应用程序的优先级。
1.1 脚本代码
#!/bin/sh
# renicename - Renices the job that matches the specified name.
user=""; tty=""; showpid=0; niceval="+1" # initialize
while getopts "n:u:t:p" opt; do
case $opt in
n ) niceval="$OPTARG"; ;;
u ) if [ ! -z "$tty" ] ; then
echo "$0: error: -u and -t are mutually exclusive." >&2
exit 1
fi
user=$OPTARG ;;
t ) if [ ! -z "$user" ] ; then
echo "$0: error: -u and -t are mutually exclusive." >&2
exit 1
fi
tty=$OPTARG ;;
p ) showpid=1; ;;
? ) echo "Usage: $0 [-n niceval] [-u user|-t tty] [-p] pattern" >&2
echo "Default niceval change is \"$niceval\" (plus is lower" >&2
echo "priority, minus is higher, but only root can go below 0)" >&2
exit 1
esac
done
shift $(($OPTIND - 1)) # eat all the parsed arguments
if [ $# -eq 0 ] ; then
echo "Usage: $0 [-n niceval] [-u user|-t tty] [-p] pattern" >&2
exit 1
fi
if [ ! -z "$tty" ] ; then
pid=$(ps cu -t $tty | awk "/ $1/ { print \\$2 }")
elif [ ! -z "$user" ] ; then
pid=$(ps cu -U $user | awk "/ $1/ { print \\$2 }")
else
pid=$(ps cu -U ${USER:-LOGNAME} | awk "/ $1/ { print \$2 }")
fi
if [ -z "$pid" ] ; then
echo "$0: no processes match pattern $1" >&2 ; exit 1
elif [ ! -z "$(echo $pid | grep ' ')" ] ; then
echo "$0: more than one process matches pattern ${1}:"
if [ ! -z "$tty" ] ; then
runme="ps cu -t $tty"
elif [ ! -z "$user" ] ; then
runme="ps cu -U $user"
else
runme="ps cu -U ${USER:-LOGNAME}"
fi
eval $runme | \
awk "/ $1/ { printf \" user %-8.8s pid %-6.6s job %s\n\", \
\$1,\$2,\$11 }"
echo "Use -u user or -t tty to narrow down your selection criteria."
elif [ $showpid -eq 1 ] ; then
echo $pid
else
# ready to go: let's do it!
echo -n "Renicing job \""
echo -n $(ps cp $pid | sed 's/ [ ]*/ /g' | tail -1 | cut -d\ -f5-)
echo "\" ($pid)"
renice $niceval $pid
fi
exit 0
1.2 脚本工作原理
该脚本借鉴了之前的脚本,将进程名映射到进程ID,但不是终止作业,而是降低其优先级。为避免意外调整多个匹配进程,若有多个进程匹配条件,脚本将失败。否则,它将进行指定的更改,并让
renice
程序报告可能遇到的任何错误。
1.3 运行脚本
运行脚本时,有以下几种选项:
-
-n val
:指定所需的
nice
(作业优先级)值,默认值为
niceval=1
。
-
-u user
:按用户限制匹配进程。
-
-t tty
:按终端名进行类似过滤。
-
-p
:仅显示匹配的进程ID,而不实际调整应用程序的优先级。
此外,
renicename
需要一个命令模式,用于与系统上运行的进程名进行比较,以确定哪些进程匹配。
1.4 运行结果示例
$ renicename "vim"
renicename: more than one process matches pattern vim:
user taylor pid 10581 job vim
user taylor pid 10949 job vim
Use -u user or -t tty to narrow down your selection criteria.
1.5 脚本扩展
可以编写另一个脚本,监视特定程序的启动,并自动将它们调整到设定的优先级。示例代码如下:
#!/bin/sh
# watch_and_nice - Watches for the specified process name, and renices it
# to the desired value when seen.
renicename="$HOME/bin/renicename"
if [ $# -ne 2 ] ; then
echo "Usage: $(basename $0) desirednice jobname" >&2
exit 1
fi
pid="$($renicename -p "$2")"
if [ ! -z "$(echo $pid | sed 's/[0-9]*//g')" ] ; then
echo "Failed to make a unique match in the process table for $2" >&2
exit 1
fi
currentnice="$(ps -lp $pid | tail -1 | awk '{print $6}')"
if [ $1 -gt $currentnice ] ; then
echo "Adjusting priority of $2 to $1"
renice $1 $pid
fi
exit 0
在
cron
作业中使用此脚本,可以确保某些应用程序在启动后几分钟内被调整到所需的优先级。
1.6 流程说明
graph TD;
A[开始] --> B[解析命令行参数];
B --> C{是否有参数缺失};
C -- 是 --> D[输出使用说明并退出];
C -- 否 --> E{是否指定终端或用户};
E -- 是 --> F[根据指定条件查找进程ID];
E -- 否 --> G[根据当前用户查找进程ID];
F --> H{是否找到进程ID};
G --> H;
H -- 否 --> I[输出未找到匹配进程信息并退出];
H -- 是 --> J{是否有多个匹配进程};
J -- 是 --> K[输出匹配进程信息并提示缩小选择范围];
J -- 否 --> L{是否仅显示进程ID};
L -- 是 --> M[输出进程ID并退出];
L -- 否 --> N[输出调整信息并执行renice命令];
N --> O[退出];
K --> O;
D --> O;
I --> O;
2. 添加新的虚拟主机账户
对于从单个服务器提供多个不同域名和网站的Web管理员来说,使用虚拟主机是一个很好的方法。虚拟主机是Apache(和许多其他Web服务器)的一项功能,可将多个域名分配给同一个IP地址,然后在Apache配置文件中拆分为各个站点。
2.1 脚本代码
#!/bin/sh
# addvirtual - Adds a virtual host to an Apache configuration file.
# You'll want to modify all of these to point to the proper directories
docroot="/etc/httpd/html"
logroot="/var/log/httpd/"
httpconf="/etc/httpd/conf/httpd.conf"
# Some sites use 'apachectl' rather than restart_apache:
restart="/usr/local/bin/restart_apache"
showonly=0; tempout="/tmp/addvirtual.$$"
trap "rm -f $tempout $tempout.2" 0
if [ "$1" = "-n" ] ; then
showonly=1 ; shift
fi
if [ $# -ne 3 ] ; then
echo "Usage: $(basename $0) [-n] domain admin-email owner-id" >&2
echo " Where -n shows what it would do, but doesn't do anything" >&2
exit 1
fi
# Check for common and probable errors
if [ $(id -u) != "root" -a $showonly = 0 ] ; then
echo "Error: $(basename $0) can only be run as root." >&2
exit 1
fi
if [ ! -z "$(echo $1 | grep -E '^www\.')" ] ; then
echo "Please omit the www. prefix on the domain name" >&2
exit 0
fi
if [ "$(echo $1 | sed 's/ //g')" != "$1" ] ; then
echo "Error: Domain names cannot have spaces." >&2
exit 1
fi
if [ -z "$(grep -E "^$3" /etc/passwd)" ] ; then
echo "Account $3 not found in password file" >&2
exit 1
fi
# Build the directory structure and drop a few files therein
if [ $showonly -eq 1 ] ; then
tempout="/dev/tty" # to output virtualhost to stdout
echo "mkdir $docroot/$1 $logroot/$1"
echo "chown $3 $docroot/$1 $logroot/$1"
else
if [ ! -d $docroot/$1 ] ; then
if mkdir $docroot/$1 ; then
echo "Failed on mkdir $docroot/$1: exiting." >&2 ; exit 1
fi
fi
if [ ! -d $logroot/$1 ] ; then
mkdir $logroot/$1
if [ $? -ne 0 -a $? -ne 17 ] ; then
# error code 17 = directory already exists
echo "Failed on mkdir $docroot/$1: exiting." >&2 ; exit 1
fi
fi
chown $3 $docroot/$1 $logroot/$1
fi
# Now let's drop the necessary block into the httpd.conf file
cat << EOF > $tempout
####### Virtual Host setup for $1 ###########
<VirtualHost www.$1 $1>
ServerName www.$1
ServerAdmin $2
DocumentRoot $docroot/$1
ErrorLog logs/$1/error_log
TransferLog logs/$1/access_log
</VirtualHost>
<Directory $docroot/$1>
Options Indexes FollowSymLinks Includes
AllowOverride All
order allow,deny
allow from all
</Directory>
EOF
if [ $showonly -eq 1 ]; then
echo "Tip: Copy the above block into $httpconf and"
echo "restart the server with $restart and you're done."
exit 0
fi
# Let's hack the httpd.conf file
date="$(date +%m%d%H%m)" # month day hour minute
cp $httpconf $httpconf.$date # backup copy of config file
# Figure out what line in the file has the last </VirtualHost> entry.
# Yes, this means that the script won't work if there are NO virtualhost
# entries already in the httpd.conf file. If there are no entries, just use
# the -n flag and paste the material in manually...
addafter="$(cat -n $httpconf|grep '</VirtualHost>'|awk 'NR==1 {print $1}')"
if [ -z "$addafter" ]; then
echo "Error: Can't find a </VirtualHost> line in $httpconf" >&2
/bin/rm -f $httpconf.$date; exit 1
fi
sed "${addafter}r $tempout" < $httpconf > $tempout.2
mv $tempout.2 $httpconf
if $restart ; then
mv $httpconf $httpconf.failed.$date
mv $httpconf.$date $httpconf
$restart
echo "Configuration appears to have failed; restarted with old config" >&2
echo "Failed configuration is in $httpconf.failed.$date" >&2
exit 1
fi
exit 0
2.2 脚本工作原理
该脚本虽然较长,但很直接,大部分内容用于各种输出消息。第一部分的错误条件检查是复杂的条件语句,其中最复杂的是检查运行脚本的用户ID。脚本在每个Unix命令后检查返回码,以确保一切正常,但如果没有
chown
命令或
chown
命令只能由root运行,则无法捕获该错误。
脚本会特别注意避免使
httpd.conf
文件损坏。它将当前
httpd.conf
文件的内容复制到临时文件中,将新的
VirtualHost
和
Directory
块注入到实时
httpd.conf
文件中,然后重启Web服务器。如果重启失败,会将实时
httpd.conf
文件移动到
http.conf.failed.MMDDHHMM
,并将旧的配置文件移回原位,再次启动Web服务器并输出错误消息。
2.3 运行脚本
此脚本需要三个参数:新域名、Apache错误消息页面的管理员电子邮件地址以及将拥有结果目录的用户账户名。若要在屏幕上显示输出而不实际修改
httpd.conf
文件,请包含
-n
标志。在运行之前,可能需要修改脚本中前几个变量的值以匹配自己的配置。
2.4 运行结果示例
$ addvirtual -n baby.net admin@baby.net taylor
mkdir /etc/httpd/html/baby.net /var/log/httpd//baby.net
chown taylor /etc/httpd/html/baby.net /var/log/httpd//baby.net
####### Virtual Host setup for baby.net ###########
<VirtualHost www.baby.net baby.net>
ServerName www.baby.net
ServerAdmin admin@baby.net
DocumentRoot /etc/httpd/html/baby.net
ErrorLog logs/baby.net/error_log
TransferLog logs/baby.net/access_log
</VirtualHost>
<Directory /etc/httpd/html/baby.net>
Options Indexes FollowSymLinks Includes
AllowOverride All
order allow,deny
allow from all
</Directory>
Tip: Copy the above block into /etc/httpd/conf/httpd.conf and
restart the server with /usr/local/bin/restart_apache and you're done.
2.5 脚本扩展
-
创建新的网站目录,并自动复制
index.html和自定义404错误页面,将404错误页面中的特定字符串(如%%domain%%)替换为新域名,将%%admin email%%替换为管理员的电子邮件地址。 -
测试并可能改进重启测试。如果重启程序在失败时不返回非零返回码,可以捕获输出并搜索特定单词(如 “failed” 或 “error”)以确定成功或失败,或者在重启后立即使用
ps|grep查看httpd是否正在运行,并做出相应响应。
2.6 流程说明
graph TD;
A[开始] --> B[解析命令行参数];
B --> C{是否有参数缺失};
C -- 是 --> D[输出使用说明并退出];
C -- 否 --> E{是否使用 -n 标志};
E -- 是 --> F[显示操作信息但不执行];
E -- 否 --> G{是否为root用户};
G -- 否 --> H[输出错误信息并退出];
G -- 是 --> I{域名是否合法};
I -- 否 --> J[输出错误信息并退出];
I -- 是 --> K{用户账户是否存在};
K -- 否 --> L[输出错误信息并退出];
K -- 是 --> M[创建目录结构并设置权限];
M --> N[生成VirtualHost配置块];
N --> O{是否使用 -n 标志};
O -- 是 --> P[输出配置块并提示手动操作];
O -- 否 --> Q[备份httpd.conf文件];
Q --> R{找到最后一个</VirtualHost>行};
R -- 否 --> S[输出错误信息并退出];
R -- 是 --> T[插入新配置块];
T --> U{重启服务器是否成功};
U -- 是 --> V[完成并退出];
U -- 否 --> W[恢复旧配置并输出错误信息];
W --> V;
P --> V;
F --> V;
D --> V;
H --> V;
J --> V;
L --> V;
S --> V;
3. Mac OS X脚本概述
Mac OS X系统基于Darwin这一可靠的Unix核心,它是基于BSD Unix的开源Unix。与Linux/Unix相比,Mac OS X有一些显著差异,例如使用NetInfo系统数据库替代了
/etc/passwd
和
/etc/aliases
等扁平信息文件。此外,Mac OS X还有一些有趣的应用和命令行工具,以下将详细介绍。
3.1 文件换行符转换
在Mac OS X中,GUI应用创建的文件换行符与命令行工作时所需的换行符不同。Aqua系统使用回车符(
\r
)作为换行符,而Unix端需要换行符(
\n
)。可以使用
tr
命令进行转换,具体操作如下:
- 将Mac Aqua文件转换为Unix格式:
$ tr '\r' '\n' < mac-format-file.txt > unix-format-file.txt
示例输入文件内容:
$ cat -v mac-format-file.txt
The rain in Spain^Mfalls mainly on^Mthe plain.^MNo kidding. It does.^M
转换后输出:
The rain in Spain
falls mainly on
the plain.
No kidding. It does.
- 将Unix文件转换为Mac格式:
$ tr '\n' '\r' < unixfile.txt > macfile.txt
3.2 屏幕截图工具
Mac OS X有内置的屏幕截图功能,可通过按下
CMD - SHIFT - 3
触发,也可使用
Grab
工具。此外,还有命令行工具
screencapture
,其使用方法如下:
$ screencapture
screencapture: illegal usage, file required if not going to clipboard
usage: screencapture [-icmwsWx] [file] [cursor]
-i capture screen interactively, by selection or window
control key - causes screen shot to go to clipboard
space key - toggle between mouse selection and
window selection modes
escape key - cancels interactive screen shot
-c force screen capture to go to the clipboard
-m only capture the main monitor, undefined if -i is set
-w only allow window selection mode
-s only allow mouse selection mode
-W start interaction in window selection mode
-x do not play sounds
file where to save the screen capture
3.2.1 定时截图示例
- 30秒后截图:
$ sleep 30; screencapture capture.tiff
- 每隔一分钟进行一次截图,共60次:
maxshots=60; counter=0
while [ $counter -lt $maxshots ] ; do
screencapture capture${counter}.tiff
counter=$((counter + 1))
sleep 60
done
3.3 流程说明
graph TD;
A[开始] --> B{选择操作类型};
B -- 文件换行符转换 --> C{选择转换方向};
C -- Mac到Unix --> D[使用 tr '\r' '\n' 转换];
C -- Unix到Mac --> E[使用 tr '\n' '\r' 转换];
B -- 屏幕截图 --> F{选择截图方式};
F -- 定时截图 --> G{设置定时参数};
G -- 单次定时 --> H[使用 sleep 和 screencapture 定时截图];
G -- 多次定时 --> I[使用循环和 screencapture 定时截图];
F -- 交互式截图 --> J[使用 screencapture -i 进行交互截图];
D --> K[结束];
E --> K;
H --> K;
I --> K;
J --> K;
3.4 总结
通过上述介绍,我们了解了在Mac OS X系统中调整进程优先级、添加虚拟主机账户以及处理文件换行符和屏幕截图的方法。这些脚本和工具可以帮助我们更高效地管理系统和完成日常任务。在实际使用中,可根据具体需求对脚本进行扩展和优化,以满足不同的场景要求。
3.5 表格总结
| 功能 | 脚本/工具 | 主要参数 | 用途 |
|---|---|---|---|
| 进程优先级调整 |
renicename
|
-n
、
-u
、
-t
、
-p
| 按进程名调整进程优先级 |
| 虚拟主机添加 |
addvirtual
|
-n
、域名、管理员邮箱、用户账户名
| 在Apache配置文件中添加虚拟主机 |
| 文件换行符转换 |
tr
|
'\r' '\n'
或
'\n' '\r'
| 转换文件的换行符格式 |
| 屏幕截图 |
screencapture
|
-i
、
-c
、
-m
、
-w
、
-s
、
-W
、
-x
| 进行屏幕截图操作 |
3.6 列表总结
-
进程优先级调整
:通过
renicename脚本,可方便地按进程名调整进程优先级,避免手动查找进程ID的麻烦。 -
虚拟主机添加
:
addvirtual脚本为Web管理员提供了自动化添加虚拟主机的功能,同时确保配置文件的安全性。 -
文件换行符转换
:使用
tr命令可轻松实现Mac Aqua文件和Unix文件换行符的转换。 -
屏幕截图
:
screencapture命令行工具结合脚本可实现定时、交互式等多种屏幕截图方式。
超级会员免费看
1636

被折叠的 条评论
为什么被折叠?



