目录
开发者在进行服务器集群管理时,都需要编写 Shell 程序来进行服务器管理。Shell 是一个命令行解释器,为用户提供了一个向 Linux 内核发送请求以便于运行程序的界面系统升级程序。用户可以用 Shell 来启动、挂起、停止或者编写一些程序。
Shell 脚本在执行时有两个格式上的要求:以 #!/bin/bash 开头、必须有可执行权限。如下我们编写第一个 Shell 脚本:
(1)创建新目录 shell 用于存放 shell 脚本;
[root@majinjian ~]# mkdir /root/shell
[root@majinjian ~]# cd /root/shell
(2)vim 编辑器新建 shell 脚本 shell.sh,输入命令;
#!/bin/bash
echo "hello world!"
(3)这个时候查看 shell.sh 的权限,是没有可执行权限 x 的;

(4)为它添加可执行权限;
[root@majinjian shell]# chmod u+x shell.sh

(5)执行文件;

shell 脚本常用的执行方式有两种:
- 输入脚本的绝对路径或者相对路径(需要先赋予脚本执行权限 x);
- sh + 脚本(无需赋予执行权限,直接执行即可)。
Linux Shell 中的变量分为系统变量和用户自定义变量。系统变量顾名思义就是系统已经设置好的变量,诸如 $HOME、$PWD、$USER、$SHELL 等都是系统变量。使用指令 set 可以查看系统中所有的系统变量。我们常用较多的是自定义变量,基本语法如下:
- 定义变量:变量名称=值;
- 撤销变量:unset 变量名;
- 定义静态变量:readonly 变量名称=值(静态变量不能撤销);
- 输出变量:$变量。
我们试着操作一下变量:
#定义变量A
A=100
#输出变量
echo A=$A
echo "A=$A"
#撤销变量A
unset A
echo $A
#声明静态的变量B = 3
readonly B=3
echo $B
执行结果为;

在定义变量时变量名称可以由字母、数字和下划线组成,但不能以数字开头;等号的两侧不能有空格;变量名称一般为大写。
将命令的返回值赋给变量时使用如下写法;
- A=`data`,表示运行 ` ` 中的命令,并把结果返回给 A;
- A=$(data),$() 相当于 ``。
- export 变量名=变量值 //将 Shell 变量输出为环境变量/全局变量
- source 配置文件 //让修改后的配置信息立即生效
- echo $变量名 //查询环境变量的值
案例:在 /etc/profile 文件中定义 TOMCAT_HOME 环境变量,vim 打开 /etc/profile 输入;
export TOMCAT_HOME=/opt/tomcat
设置完之后刷新配置状态;
[root@majinjian opt]# source /etc/profile
结果如下;

当执行一个 Shell 脚本时,如果希望获取到命令行的参数信息,就需要使用到位置参数变量。基本语法有:
- $n //n 为数字,$0 代表命令本身,$1-9 代表第 1 到第 9 个参数,10 以上的参数需要用大括号包含如 ${10}
- $* //代表命令行中的所有参数,$* 将所有参数看成一个整体
- $@ //这个变量也可以代表命令行中的所有参数,不过 $@ 把每个参数区分对待
- $# //代表命令行中所有参数的个数
案例:编写一个 Shell 脚本 position.sh,在脚本中获取到命令行中的各个参数信息。
#!/bin/bash
echo "0=$0 1=$1 2=$2"
echo "所有参数=$*"
echo "$@"
echo "参数个数=$#"
运行时输入 100 和 200 两个参数,结果如下。

预定义变量就是 Shell 的设计者事先定义好的变量,可以直接在 Shell 脚本中使用。基本语法有:
- $$ //当前进程的进程号码(PID)
- $! //后台运行的最后一个进程的进程号
- $? //最后一次执行命令的返回状态,如果这个变量的值为0证明上一个命令正确执行,如果不是 0 上一个命令没有正确执行
在 Shell 编程中有各种运算操作,语法格式为 $((运算式)) 或 $[运算式] 或者 expr m + n;如果希望将 expr 的值赋给某个变量,使用 `` 即可。
- \* //乘,在 `` 里面的乘应该用此格式即 * 前添加转义字符 \
- / //除
- % //取余
案例1:计算 (2+3)×4;
#!/bin/bash
#计算(2+3)×4的值
#方式1
result1=$(((2+3)*4))
echo "res1=$result1"
#方式2
result2=$[(2+3)*4]
echo "res2=$result2"
#方式3
result3=`expr 2 + 3`
result4=`expr $result3 \* 4`
echo "expr res4=$result4"
结果如下。

案例2:计算命令行两个参数的和;
#计算命令行两个参数的和
sum=$[$1+$2]
echo "sum=$sum"
运行时输入 20 和 50,结果如下:

条件判断使用语法 [ condition ](注意 condition 前后有空格),非空会返回 true。可以使用 $? 验证结果,0 为 true,>1 为false。如:
- [ hspEdu ] 会返回 true
- [ ] 会返回 false
- [ condition ] && echo yes || echo no ,前一个判断满足时会继续执行后面的语句
常用的判断语句有:
判断两个字符串
- = //相等
判断两个整数
- -lt //小于
- -le //小于等于
- -eq //等于
- -gt //大于
- -ge //大于等于
- -ne //不等于
按照文件权限进行判断
- -r //有读的权限
- -w //有写的quanx
- -x //有执行的权限
按照文件类型进行判断
- -f //文件存在并且是一个常规的文件
- -e //文件存在
- -d //文件存在并是一个目录
案例:判断 "ok" 是否等于 ok;
#!/bin/bash
if [ "ok" = "ok" ]
then
echo "equal" #如果等于则输出 equal
fi #否则结束
22 是否大于等于 21;
if [ 22 -ge 21 ]
then
echo "大于"
fi
/root/shell 目录下是否有 aaa.txt 文件;
if [ -f /root/shell/aaa.txt ]
then
echo "存在"
fi
执行结果如下:

if 语句的基本语法如下,需要注意 [ 条件判断式 ] 中括号与判断式之间必须有空格。
#单分支
if [ 条件判断式 ]
then
代码
fi
#多分支
if [ 条件判断式 ]
then
代码
elif [ 条件判断式 ]
then
代码
fi
案例:编写一个 shell 程序,如果输入的参数大于等于 60,输出“及格”,小于 60 则输出“不及格”。
#!/bin/bash
if [ $1 -ge 60 ]
then
echo "及格"
elif [ $1 -le 60 ]
then
echo "不及格"
fi
运行时带参数结果如下;

基本语法如下,其中 * 代表都不是以上的值。
case $变量名 in
"值1")
如果变量的值等于1,则执行程序1
;;
"值2")
如果变量的值等于2,则执行程序2
;;
......
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
案例:编写 Shell 程序当命令行参数为 1 时输出“周一”,是 2 时输出“周二”,其他情况均输出“other”。
#!/bin/bash
case $1 in
"1")
echo "周一"
;;
"2")
echo "周二"
;;
*)
echo "other"
;;
esac
运行结果如下:

for 循环有两个基本语法,语法一:
for 变量 in 值1 值2 值3...
do
程序
done
案例1:打印命令行输入的参数;
#!/bin/bash
#使用$*
for i in "$*"
do
echo "num is $i"
done
#使用$@
for i in "$@"
do
echo "num is $i"
done
运行结果如下,这也印证了 $*(将所有参数看成一个整体) 和 $@(将参数区别对待) 的区别;

除此之外 for 循环还有第二个语法;
for((初始值;循环控制条件;变量变化))
do
程序
done
案例2:输出从 1 加到 100 的值。
#!/bin/bash
sum=0
for(( i=1;i<=100;i++ ))
do
sum=$[$sum+$i]
done
echo "SUM=$sum"
运行结果如下:

基本语法:
while [ 条件判断式 ]
do
程序
done
案例:命令行输入一个参数 n,计算 1+2+..+n 的值;
#/bin/bash
sum=0
i=0
while [ $i -le $1 ] #只要第i个数小于我们输入的参数,就执行循环
do
sum=$[$sum+$i]
i=$[$i+1] #i自增
done
echo "SUM=$SUM"
运行结果如下:

在我们进行 Shell 编程的时候,有时候也需要跟控制台进行交互,比如用户动态的输入一些数据,这个时候就需要用到 read。基本语法为
read(选项)(参数)
- -p 制定读取值时的提示符
- -t 指定读取值时的等待时间,如果没有在规定时间内输入,则不再等待
案例 1:读取控制台输入一个 num 值;
#!/bin/bash
read -p "输入num1=:" num1
echo "你输入的num1为:$num1"
运行结果如下:

案例 2:读取控制台输入一个 num 值,指定在 10 秒内输入;
read -t 10 -p "输入num2=" num2
echo "你输入的num2为:$num2"
运行结果如下:

我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。