• [技术干货] shell输出重定向的实现【转】
    1.输入输出重定向介绍重定向简单来说就是把本来已经默认的、确定的输入输出给重新定位到你想要的地方。 重定向这个概念在C语言中就有,在C语言编程中,标准输出是屏幕,使用printf()函数默认是输出到屏幕显示。但是有时候我们需要将信息输出到文件或者申请的内存中,这时候就可以用sprintf()和fprintf()函数;也可以将标准输出的文件描述符给强行占用,使标准输出的文件描述符指向自己想要的文件。在shell中默认打开了三个文件,分别是标准输出(文件描述符0)、标准输出(文件描述符1)、错误输出(文件描述符2),标准输入默认是键盘,标准输出和错误输出默认是屏幕。2.>和>>介绍解析:>和>>都是重定向的符号,符号的左边表示文件描述符或者要重定位的内容,如果不写默认是文件描述符1,即标准输出;右边可以是文件也可以是设备。1.当使用>时,如果右边的文件存在则会先删除在创建,如果右边的文件不存在则创建;2.当使用>>时,表示追加,右边的文件不会被删除,新的内容会添加到文件的末尾。3.命令:>/dev/null 2>&1解析:这可以理解成两句指令:>/dev/null 和 2>&1(1)>/dev/null :将文件描述符1重定向到/dev/null,文件描述符1是标准输出,/dev/null在linux中是空的设备文件,所以往这个设备文件输入的内容都会丢失;这句指令的作用就是将标准输出重定向到/dev/null这个空的设备文件里,效果就是全部的输出都会丢掉。(2)2>&1:将文件描述符2重定向到文件描述符1指向的地方,也就是空的设备文件。执行该指令后,标准输出和错误输出都往空设备文件里写,效果就是两者都丢不再打印到屏幕。4.命令:2>&1 >/dev/null解析:同样分成两个语句理解、(1)2>&1:将文件描述符2重定向到文件描述符1指向的地方,此时标准输出是屏幕。该指令的效果是标准输出和错误输出都输出到屏幕。(2)>/dev/null:将标准输出重定向到空的设备文件,即屏幕不再打印标准输出;但是错误输出此时还是会往屏幕输出,因为错误输出并没有重定向到空的设备文件。5.总结:(1)**>/dev/null 2>&1:**标准输出和错误输出都舍弃掉;(2)**2>&1 >/dev/null:**标准输出被舍弃掉,错误输出被重定位到屏幕;在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流即stdin stdout stderr。在shell里面,分别用0,1,2代表stdin stdout stderr。stdin默认从键盘接收输入,而stdout和stderr默认向console输出。echo默认将hello送到stdout显示。而"|"管道符接收来自stdout的输入 。所以echo hello的结果被送到grep处理,最终显示hello。示例2echo hello本来是要把hello输出到stdout,但是由于1>&2的作用,最终hello交给了stderr。其实stderr也是在console上显示,所以输出结果是hello。但是管道符|只收到stdout,收不到stderr的数据,所以hello传不到grep,最终只通过stderr打印hello。再举一个从stderr向stdout定向的示例3ls 查找一个并不存在的文件,将打印错误信息将ls c.cpp与 grep cpp连用,打印相同的信息。但是这是出错信息,通过stderr输出的,而管道符只接受stdout的输出所以grep不处理信息,打印出来的cpp字符串也不标红。只有把stderr重定向到stdout---2>&1,才能让grep起作用,看到标红的cpp。
  • [技术干货] shell wait等待命令的具体使用【转】
    1. 简介bash wait 命令是一个 Shell 命令,它等待后台运行的进程完成并返回退出状态。与等待指定时间的sleep 命令不同,该wait命令等待所有或特定后台任务完成。2. 语法在 bash 脚本中使用wait命令有不同的方法。下表解释了每个用例。命令解释wait如果没有任何参数,该wait命令会等待所有后台进程完成,然后再继续执行脚本。wait添加的 PID 或作业 ID 会等待特定进程结束,然后再继续执行脚本。wait -n仅等待以下后台进程完成并返回退出状态。wait -f终止程序首先等待后台任务完成后再退出。3. 示例3.1 等待命令在 bash 脚本中使用wait时需要了解三个附加参数:1.&命令后的和号 ( ) 表示后台作业。2.$!获取最后一个后台进程的PID。使用多个后台进程时,将先前的 PID 存储在一个变量中。3.$?打印上一个进程的退出状态。要查看这三个参数如何协同工作,请打开终端窗口并运行:sleep 10 & echo $! echo $? 该$!参数存储后台进程PID,同时$?存储退出状态。退出状态0表示命令成功完成。3.2 单进程等待首先打开终端并创建一个简单的后台进程:1sleep 10 &确认作业在后台运行:1jobs -l使用wait不带任何参数的命令暂停直到进程完成:1wait10 秒后(由于sleep 10),控制台打印完成消息。3.3 单进程 bash 等待使用该wait命令指示后台进程必须在脚本内执行的时间点。例如,在文本编辑器中添加以下代码:#!/bin/bash echo Background process & echo First message echo Second message wait echo Third message 如果后台进程没有完成第一个和第二个进程,则该wait命令调用暂停以等待第二个进程之后后台进程完成,然后再继续执行第三个进程。将脚本另存为single_process.sh。在终端中,更改权限以使脚本可执行:1sudo chmod +x single_process.sh运行脚本:1./single_process.sh后台进程在命令之前的任何时间完成wait,并且脚本继续。3.4 多个进程等待1.打开文本编辑器,添加以下多进程脚本:#!/bin/bash sleep 10 & sleep 15 & sleep 5 & echo $(date +%T) wait  echo $(date +%T) wait该脚本在命令之前和之后打印当前时间。没有任何参数,程序会等待所有进程完成。将脚本另存为test.sh并关闭文件。接下来,使脚本可执行:1sudo chmod +x test.sh最后,运行程序:1./test.sh由于进程在后台运行,所有三个进程都在十五秒内完成。使用相同的脚本测试以下用例:将-n参数添加到<strong>wait</strong>. 只有最快的过程完成,脚本在十秒后结束。添加作业 ID 以指示脚本应等待哪个作业。例如,wait %1暂停以等待进程 1 ( sleep 10) 完成。3.5 多个进程 bash 等待 PID与多个进程一起工作时,使用 PID 来标识一个进程。下面的示例脚本显示了一个用例:#!/bin/bash echo "Process 1 lasts for 2s" && sleep 2 & PID=$! echo "Process 2 lasts for 3s" && sleep 3 & echo "Current time $(date +%T)" wait $PID echo "Process 1 ended at time $(date +%T) with exit status $?" wait $! echo "Process 2 ended at time $(date +%T) with exit status $?" 将脚本另存为multi_wait.sh。使脚本可执行:1sudo chmod +x multi_wait.sh运行脚本查看输出:1./multi_wait.sh
  • [技术干货] Bash EOF的使用小结【转】
    EOF适用场景:命令行多行输出脚本包装类型配置文件1. 命令行输出$ cat << EOF > Hello > EOF Hello2. 写入文本cat << EOF >1.txt 111 222 333 EOF复制终端是这样的。cat << EOF >1.txt > 111 > 222 > 333 > EOF回车后$ cat 1.txt 111 222 3333. 追加文本cat << EOF >> 1.txt 444 555 666 EOF查看1.txt内容$ cat 1.txt 111 222 333 444 555 6664. 覆盖文本cat << EOF >1.txt aaa bbb ccc EOF查看$ cat 1.txt aaa bbb ccc5. 自定义 EOFcat << a > 1.txt 111 222 333 a输出:$ cat 1.txt1112223336. 另一种格式cat > filename <<EOFcat << EOF > filenamecat > 1.txt <<EOF 123 456 789 EOF查看$ cat 1.txt 123 456 7897. 示例7.1 配置文件或者cat << EOF > /usr/local/mysql/my.cnf cat > /usr/local/mysql/my.cnf << EOF          [client] port = 3306 socket = /usr/local/mysql/var/mysql.sock  [mysqld] port = 3306 socket = /usr/local/mysql/var/mysql.sock  basedir = /usr/local/mysql/ datadir = /data/mysql/data pid-file = /data/mysql/data/mysql.pid user = mysql bind-address = 0.0.0.0 server-id = 1 sync_binlog=1 log_bin = mysql-bin  [myisamchk] key_buffer_size = 8M sort_buffer_size = 8M read_buffer = 4M write_buffer = 4M  sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES  port = 3306 EOF 7.2 新建分区并挂载$ cat auto_add_disk.sh          #!/bin/bash fdisk  /dev/sdb  <<EOF n p 1     wq EOF   /sbin/mkfs .ext4  /dev/sdb1  &&   /bin/mkdir  -p  /data  &&  /bin/mount  /dev/sdb1  /data echo  'LABEL=data_disk /data ext4 defaults 0 2'  >>  /etc/fstab7.3 设置变量 $ sql=$(cat <<EOF SELECT foo, bar FROM db WHERE foo='baz' EOF )  $ echo -e "$sql" 
  • [技术干货] Window11 WSL2 添加静态IP的脚本【转】
    Window11 WSL2 添加静态IP的脚本方法1.在WSL2 Linux中创建一个脚本文件vim /home/likfees/Shell/static-ip.sh #!/bin/bash  /mnt/c/WINDOWS/system32/netsh.exe interface ip show addresses "vEthernet (WSL)" | /mnt/c/WINDOWS/system32/findstr.exe /C:"172.18.16.1" > /dev/null if [ $? == 1 ]; then   /mnt/c/WINDOWS/system32/netsh.exe interface ip add address "vEthernet (WSL)" address=172.18.16.1/24 fi  ip addr show eth0 | grep -s "172.18.16.100/24" > /dev/null if [ $? == 1 ]; then   ip addr add 172.18.16.100/24 broadcast 172.18.16.255 dev eth0 label eth0:1 fi 注:这段脚本给 Windows 端的"vEthernet (WSL)"加了IPv4 172.18.16.1,给 Linux 端的 eth0 添加 IPv4 172.18.16.1。在使用前,请按需调整网络接口的名称和IP地址。2.在 WSL2 启动的时候执行该脚本vim /etc/profile 添加以下内容sudo /home/likfees/Shell/static-ip.sh当然如果让 eth0 重新获取了 IP,那么需要手动运行 static-ip.sh。3.win11 能够 ping 通 wsl2,但是 wsl2 无法 ping 通 win11, 经分析主要是 win11 防火墙的原因.在 win11 中 执行如下命令(管理员运行 powershell 或 cmd ):New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow 4.使用静态IP​Windows 端静态IP 172.18.16.1​WSL Linux 端静态IP 172.18.16.100ps:Win11 wsl2 固定IP方案背景win11 上通过wsl2安装了Ubuntu,想其他电脑通过ssh登入Linux,但每次电脑重启,wsl的IP会变,网上找了个脚本,可以固定wsl的IP。脚本@echo off setlocal enabledelayedexpansion ::先停掉可能在跑的wsl实例 wsl --shutdown ubuntu if !errorlevel! equ 0 (     ::检查WSL有没有我需要的IP     wsl -u root ip addr | findstr "192.168.3.100" > nul     if !errorlevel! equ 0 (         echo wsl ip has set     ) else (         ::IP不存在则绑定IP         wsl -u root ip addr add 192.168.3.100/24 broadcast 192.168.3.255 dev eth0 label eth0:1         echo set wsl ip success: 192.168.3.100     )     ::检查宿主机有没有我需要的IP     ipconfig | findstr "192.168.3.200" > nul     if !errorlevel! equ 0 (         echo windows ip has set     ) else (         ::IP不存在则绑定IP         netsh interface ip add address "vEthernet (WSL)" 192.168.3.200 255.255.255.0         echo set windows ip success: 192.168.3.200     ) )  ::为主机设置SSH转发端口  netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=22 connectaddress=192.168.3.100 connectport=22 pause
  • [技术干货] Shell脚本read用法实现【转】
    1.概述到目前为止,编写的脚本都缺少一个常用于大多数计算机程序的特性–交互性,或者说与用户互动的能力。尽管很多程序并不需要是交互式的,但能够直接接受用户输入,确实有利于某些程序。2. read从标准输入读取值内建命令read可用于从标准输入中读取一行。该命令可以读取键盘输入,如果使用了重定向,也可以读取文件的数据行。该命令用法如下:read [-options] [variable...]其中,option是一个或多个选项,variable是一个或多个变量,用于保存输入值。如果未指定变量,则输入值保存在Shell变量REPLAY中。使用read命令改写之前的整数验证脚本: #!/bin/bash  # read-integer  echo -n "Please enter an integer -> " read int  if [[ "$int" =~ ^-?[0-9]+$ ]]; then         if [ "$int" -eq 0 ]; then                 echo "$int is zero."         else                 if [ "$int" -lt 0 ]; then                         echo "$int is negative."                 else                         echo "$int is positive"                 fi         fi         if [ $((int % 2)) -eq 0 ]; then                 echo "$int is even."         else                 echo "$int is odd."         fi else         echo "Input value is not an integer." >&2         exit 1 fi read也可以将输入赋给多个变量 [sysadmin@ansible bin]$ cat read1 #!/bin/bash  #read-multiple  echo -n "Enter one or more values > " read var1 var2 var3 var4 var5  echo "var1 = '$var1'" echo "var2 = '$var2'" echo "var3 = '$var3'" echo "var4 = '$var4'" echo "var5 = '$var5'" [sysadmin@ansible bin]$ read1 Enter one or more values > 1 2 3 4 5 var1 = '1' var2 = '2' var3 = '3' var4 = '4' var5 = '5' 如果read接收到的值数量少于预期,则多出的变量为空值,如果数量多于预期,则额外的输入全部保存在最后一个变量中。 [sysadmin@ansible bin]$ cat read1 #!/bin/bash  #read-multiple  echo -n "Enter one or more values > " read var1 var2 var3 var4 var5  echo "var1 = '$var1'" echo "var2 = '$var2'" echo "var3 = '$var3'" echo "var4 = '$var4'" echo "var5 = '$var5'" [sysadmin@ansible bin]$ read1 Enter one or more values > a var1 = 'a' var2 = '' var3 = '' var4 = '' var5 = '' [sysadmin@ansible bin]$ read1 Enter one or more values > a b c d e f g var1 = 'a' var2 = 'b' var3 = 'c' var4 = 'd' var5 = 'e f g' [sysadmin@ansible bin]$ 如果没有为read命令指定变量,则所有的输入全部保存在Shell变量REPLY中 [sysadmin@ansible bin]$ cat read2 #!/bin/bash  #read-multiple  echo -n "Enter one or more values > " read  echo "REPLY = '$REPLY'" [sysadmin@ansible bin]$ read2 Enter one or more values > a b c d REPLY = 'a b c d' [sysadmin@ansible bin]$ 2.1 read选项选项描述-a array将输入分配给数组(从索引0开始)。-d delimiter将字符串delimter中的第一个字符(而非换行符)作为输入的结束-e使用readline处理输入,允许使用和命令行相同的方式编辑输入-i string如果用户直接按Enter键,使用string作为默认值,需要配合-e选项使用-n num从输入中读取num个字符,而非读取一整行-p prompt将字符prompt作为输入提示来显示-r原始模式,不将反斜线符解释为转义-s静默模式,在用户输入字符时不回显,该模式适用于输入密码或其他机密信息-t seconds超时,seconds秒之后终止输入,如果输入超时,read返回非0退出状态值-u fd从文件描述符fd中读取输入选项-p [sysadmin@ansible bin]$ cat read2 #!/bin/bash  #read-single  read -p "Enter one or more values > "  echo "REPLY = '$REPLY'" [sysadmin@ansible bin]$ read2 Enter one or more values > a REPLY = 'a' [sysadmin@ansible bin]$ 选项-t和-s [sysadmin@ansible bin]$ cat readpass #!/bin/bash  #read-pass  if read -t 10 -sp "Enter password > " passwd; then         echo -e "\nSecret passphrase = '$passwd'" else         echo -e "\nInput timed out" >&2         exit 1 fi [sysadmin@ansible bin]$ readpass Enter password > Secret passphrase = 'abcdef' [sysadmin@ansible bin]$ 选项-e和-i [sysadmin@ansible bin]$ cat readdefault #!/bin/bash  #read-default  read -e -p "What is your user name? " -i $USER echo "You answered: '$REPLY'" [sysadmin@ansible bin]$ readdefault What is your user name? sysadmin You answered: 'sysadmin' [sysadmin@ansible bin]$ 2.2 IFSShell通常会提供给read的输入进行单词分割,这意味着输入行中被一个或多个空白字符分割的多个单词会变成若干独立项,再由read分配给各个变量。Shell变量内部字段分割符(Internal Filed Separator,IFS)控制着此行为。IFS的默认值包含了空格符,制表符,换行符,它们都可用于分割单词。我们可以调整IFS的值,控制read的输入字段。例如:/etc/passwd文件中的数据行采用冒号作为字段分隔符。将IFS的值改成冒号,就可以使用read读入/etc/passwd的内容并顺利将字段分割存入各个变量。来看下面的实现脚本。 [sysadmin@ansible bin]$ cat read-ifs #!/bin/bash  # read-ifs  FILE=/etc/passwd  read -p "Enter a user > " user_name  file_info="$(grep "^$user_name:" $FILE)"  if [ -n "$file_info" ]; then         IFS=":" read user pw uid gid name home shell <<< "$file_info"         echo "User =            '$user'"         echo "UID =             '$uid'"         echo "GID =             '$gid'"         echo "Full Name =       '$name'"         echo "Home Dir =        '$home'"         echo "Shell =           '$shell'" else         echo "No such user '$user_name'" >&2         exit 1 fi [sysadmin@ansible bin]$ read-ifs Enter a user > jticnoc User =          'jticnoc' UID =           '2099' GID =           '2099' Full Name =     '' Home Dir =      '/home/jticnoc' Shell =         '/bin/bash' [sysadmin@ansible bin]$ Shell允许一个或多个变量赋值直接出现在命令之前。这些赋值会修改紧随其后的命令的环境。这种赋值效果是临时的。对环境所作的改动仅限于命令执行期间有效。<<< 标识here string。here string类似于here document,但是更简短,仅由单个字符串组成。2.3 验证输入好程序和差程序之间的区别往往在于处理意外情况的能力,而意外情况多以错误输入的形式出现。重要的是,每次程序接收到输入的时候,都要执行此类检查,以防止非法数据。 [sysadmin@ansible bin]$ cat read-validate #!/bin/bash  #read-validate  invalid_input () {         echo "Invalid input '$REPLAY'" >&2         exit 1 }  read -p "Enter a single item > "  # input is null [[ -z "$REPLY" ]] && invalid_input  # input is multi items (( "$(echo "$REPLY" |wc -w)" > 1 )) && invalid_input  # input filename is valid if [[ "$REPLY" =~ ^[-[:alnum:]\._]+$ ]]; then         echo "'$REPLY' is a valid filename."         if [[ -e "$REPLY" ]]; then                 echo "And file '$REPLY' exists."         else                 echo "However, file '$REPLY' does not exist."         fi          # input is float         if [[ "$REPLY" =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then                 echo "'$REPLY' is a floating point number."         else                 echo "'$REPLY' is not a floating point number."         fi          # input is int         if [[ "$REPLY" =~ ^-?[[:digit:]]+$ ]]; then                 echo "'$REPLY' is an integer."         else                 echo "'$REPLY' is not an integer."         fi else         echo "The string '$REPLY' is not a valid filename." fi [sysadmin@ansible bin]$ 2.4 菜单菜单驱动是一中常见的交互方式,菜单驱动的程序会为用户呈现一系列的选项,要求用户从中选择。 [sysadmin@ansible bin]$ cat read-menu #!/bin/bash  #read-menu  clear echo " Please Select:  1.Display System Information 2.Display Disk Space 3.Display Home Space Utilization 4.Quit " read -p "Enter selection [0-3] > "  if [[ "$REPLY" =~ ^[0-3]$ ]]; then         if [[ "$REPLY" == 0 ]]; then                 echo "Program terminated."                 exit         fi          if [[ "$REPLY" == 1 ]]; then                 echo "Hostname: $HOSTNAME"                 uptime                 exit         fi          if [[ "$REPLY" == 2 ]]; then                 df -h                 exit         fi          if [[ "$REPLY" == 3 ]]; then                 if [[ "$(id -u)" -eq 0 ]]; then                         echo "Home Space Utilization (ALL Users)"                         du -sh /home/*                 else                         echo "Home Space Utilizaion ($USER)"                         du -sh "$HOME"                 fi                 exit         fi else         echo "Invalid entry." >&2         exit 1 fi 第一部分展示了菜单并获取用户输入,第二部分识别输入并执行相应的菜单项功能。注意脚本中exit命令的用法,在完成用户选定的功能后,exit可以防止继续执行不必要的代码。
  • [技术干货] Shell[[]]检测某个条件是否成立【转】
    [[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 还能做到。可以认为 [[ ]] 是 test 的升级版,对细节进行了优化,并且扩展了一些功能。[[ ]] 的用法为:1[[ expression ]]当 [[ ]] 判断 expression 成立时,退出状态为 0,否则为非 0 值。注意[[ ]]和expression之间的空格,这两个空格是必须的,否则会导致语法错误。[[ ]] 不需要注意某些细枝末节[[ ]] 是 Shell 内置关键字,不是命令,在使用时没有给函数传递参数的过程,所以 test 命令的某些注意事项在 [[ ]] 中就不存在了,具体包括:不需要把变量名用双引号""包围起来,即使变量是空值,也不会出错。不需要、也不能对 >、< 进行转义,转义后会出错。请看下面的演示代码:#!/bin/bash   read str1 read str2   if [[ -z $str1 ]] || [[ -z $str2 ]]  #不需要对变量名加双引号 then     echo "字符串不能为空" elif [[ $str1 < $str2 ]]  #不需要也不能对 < 进行转义 then     echo "str1 < str2" else     echo "str1 >= str2" fi运行结果:http://c.biancheng.net/shell/http://data.biancheng.net/str1 < str2[[ ]] 支持逻辑运算符对多个表达式进行逻辑运算时,可以使用逻辑运算符将多个 test 命令连接起来,例如:1[ -z "$str1" ] || [ -z "$str2" ]你也可以借助选项把多个表达式写在一个 test 命令中,例如:1[ -z "$str1" -o -z "$str2" ]但是,这两种写法都有点“别扭”,完美的写法是在一个命令中使用逻辑运算符将多个表达式连接起来。我们的这个愿望在 [[ ]] 中实现了,[[ ]]  支持 &&、|| 和 ! 三种逻辑运算符。使用 [[ ]] 对上面的语句进行改进:1[[ -z $str1 || -z $str2 ]]这种写法就比较简洁漂亮了。注意,[[ ]] 剔除了 test 命令的-o和-a选项,你只能使用 || 和 &&。这意味着,你不能写成下面的形式:1[[ -z $str1 -o -z $str2 ]]当然,使用逻辑运算符将多个 [[ ]] 连接起来依然是可以的,因为这是 Shell 本身提供的功能,跟 [[ ]] 或者 test 没有关系,如下所示:1[[ -z $str1 ]] || [[ -z $str2 ]]该表总结了各种写法的对错test 或 [][[ ]][ -z "$str1" ] || [ -z "$str2" ]√[[ -z $str1 ]] || [[ -z $str2 ]]√[ -z "$str1" -o -z "$str2" ]√[[ -z $str1 -o -z $str2 ]]×[ -z $str1 || -z $str2 ]×[[ -z $str1 || -z $str2 ]]√[[ ]] 支持正则表达式在 Shell [[ ]] 中,可以使用=~来检测字符串是否符合某个正则表达式,它的用法为:[[ str =~ regex ]]  str 表示字符串,regex 表示正则表达式。下面的代码检测一个字符串是否是手机号:#!/bin/bash   read tel   if [[ $tel =~ ^1[0-9]{10}$ ]] then     echo "你输入的是手机号码" else     echo "你输入的不是手机号码" fi运行结果1:13203451100你输入的是手机号码运行结果2:132034511009你输入的不是手机号码对^1[0-9]{10}$的说明:^匹配字符串的开头(一个位置)[0-9]{10}匹配连续的十个数字$匹配字符串的末尾(一个位置)有了 [[ ]],你还有什么理由使用 test 或者 [ ],[[ ]] 完全可以替代之,而且更加方便,更加强大。但是 [[ ]] 对数字的比较仍然不友好,所以我建议,以后大家使用 if 判断条件时,用 (()) 来处理整型数字,用 [[ ]] 来处理字符串或者文件。
  • [技术干货] shell脚本体系知识(5)
    基本重定向软件设计认为,程序应该有一个数据来源、数据出口和报告错误的地方。在 Linux 系统中,每个程序默认都会打开三个文件描述符 (file descriptor,fd):fd=0:标准输入,表示程序默认从哪里读取数据fd=1:标准输出,表示程序默认将数据输出到哪里fd=2:标准错误,表示程序默认将错误信息输出到哪里文件描述符,说白了就是系统为了跟踪打开的文件而分配给它的一个数字,这个数字和文件有对应关系:从文件描述符读取数据,即表示从对应的文件中读取数据,向文件描述符写数据,即表示向对应文件中写入数据。Linux 中万物皆文件,文件描述符也是文件。默认:fd=0 的标准输入是 /dev/stdin 文件fd=1 的标准输出是 /dev/stdout 文件fd=2 的标准错误是 /dev/stderr 文件这些文件默认又是各个终端的软链接文件:所以,默认情况下读写数据都是终端,例如:改变文件描述符对应的目标,可以改变数据的流向。比如标准输出 fd=1 默认流向是终端设备,若将其改为 /tmp/a.log,便能让数据写入 /tmp/a.log 文件中而不再是终端设备中。在 Shell 中,这种改变文件描述符目标的行为称为重定向,即重新确定数据的流向。其实,文件描述符有很多类操作,包括 fd 的重定向、fd 的分配 (open,即打开文件)、fd 复制 (duplicate)、fd 的移动 (move)、fd 的关闭 (close)。现在只介绍基础重定向操作。Shell 中,基础重定向操作有以下几种方式:[n]>file:覆盖式输出重定向,输出到 fd=n 的数据改变流向输出到 file 文件中,file 不存在则创建,file 存在则先清空再写入数据省略 n 时 >file,等价于 1>file,即标准输出覆盖重定向到 file 文件中[n]>>file:追加式输出重定向,输出到 fd=n 的数据改变流向输出到 file 文件的尾部,file 不存在则创建,file 存在则直接追加在文件尾部省略 n 时 >>file,等价于 1>>file,即标准输出追加重定向到 file 文件中[n]<file:输入重定向,以读取模式打开 file 文件并分配 fd=n,file 不存在则报错省略 n 时 <file,等价于 0<file,即直接从 file 中读数据通常程序都只从 fd=0 中读数据,所以当 n 不等于 0 时,需要多做一步操作 3<file <&3,看不懂先跳过&>file:这是特殊的重定向方式,表示将标准错误和标准输出都重定向到 file 文件中,等价于 >file 2>&1&>>file:这是特殊的重定向方式,表示将标准错误和标准输出都追加到 file 文件中,等价于 >>file 2>&1另外,经常用于输出的一个特殊目标文件是 /dev/null,它是空设备,可以直接丢掉所有写入它的数据。echo www.junmajinlong.com >/dev/null curl -I www.junmajinlong.com 2>/dev/null >/tmp/a.log cat </etc/fstab一个经常用的技巧是清空文件的方式:$ cat /dev/null >file $ >file区分 cat <file 和 cat filecat 是一个命令,这个命令的源代码中写了一些代码用来处理选项和参数。cat -n /etc/fstabcat 命令开始执行后,会识别 -n 选项,该选项会让 cat 输出时同时输出行号,cat 同时还会识别 /etc/fstab 参数,cat 会读取参数指定的文件然后输出。如果没有指定 cat 的文件参数,则 cat 默认会从标准输入中读取数据。默认的标准输入是终端,所以在没有改变标准输入的流向时,会从终端读取数据,也就是用户输入什么字符,就读取什么字符,然后输出什么字符:$ cat junmajinlong # 在终端输入 junmajinlong # 在终端输出 junma # 在终端输入 junma # 在终端输出 ^C但用户可以改变标准输入的来源。比如:$ cat </etc/fstab表示将标准输入来源改为 /etc/fstab 文件,于是 cat 会从 /etc/fstab 中读取数据。另外,约定俗成的,会使用一个 - 来表示标准输入或标准输出。下面是等价的,都表示从标准输入中读取数据cat - cat /dev/stdin cat注:这并非是一贯正确的,只是约定俗成的大多数程序的代码中都定义了 - 相关的代码处理。可参考相关命令的 man 手册。如 man cat 中有一行:With no FILE, or when FILE is -, read standard input.
  • [技术干货] shell脚本体系知识(4)
    后台执行命令在命令的结尾使用 & 符号,可以将这个命令放入后台执行。命令放入后台后,会立即回到 Shell 进程,Shell 进程会立即执行下一条命令 (如果有) 或退出。使用 $! 可以获取最近一个后台进程的 PID。sleep 20 & echo $!使用 wait 命令可以等待后台进程 (当前 Shell 进程的子进程) 完成:wait [n1 n2 n3 ...]不给定任何参数时,会等待所有子进程 (即所有后台进程) 完成。sleep 5 & wait echo haha多命令组合Shell 中有多种组合多个命令的方式。1.cmd1 退出后,执行 cmd2cmd1;cmd22.cmd1 正确退出 (退出状态码为 0) 后,执行 cmd2cmd1 && cmd23.cmd1 不正确退出后,执行 cmd2cmd1 || cmd2逻辑结合:&& 和 || 可以随意结合将多个命令分组:小括号或大括号可以组合多个命令
  • [技术干货] shell脚本体系知识(3)
    命令替换使用反引号或 $() 可以执行命令替换。`cmd` $(cmd)命令替换是指先执行 cmd,将 cmd 的输出结果替换到 $() 或反引号位置处。例如:echo `id root` echo $(id root)在 echo 命令执行前,会先执行 id 命令,id 命令的执行结果:$ id root uid=0(root) gid=0(root) groups=0(root)所以会将结果 js uid=0(root) gid=0(root) groups=0(root)替换 $(id root)。于是,echo 命令开始执行时,命令行已经变成了:echo uid=0(root) gid=0(root) groups=0(root)算术运算$[] 或 $(()) 或 let 命令可以做算术运算。let 是单独的命令,不能写在其它命令行中。a=3 let a=a+1 echo $a$[] 和 $(()) 可以写在命令行内部,Shell 在解析命令行的时候,会对它们做算术运算,然后将运算结果替换到命令行中。a=33 echo $[a+3] echo $((a+3))因为变量替换先于算术替换,所以,使用变量名或引用变量的方式都可以:a=333 echo $[$a+3] echo $(($a+3))退出状态码每个命令执行后都会有对应的进程退出状态码,用来表示该进程是否是正常退出。所以,在命令行中,在 Shell 脚本中,经常会使用特殊变量 $? 判断最近一个前台命令是否正常退出。通常情况下,如果 $? 的值:为 0,表示进程成功执行,即正常退出非 0,表示进程未成功执行,即非正常退出但非 0 退出状态码并不一定表示错误,也可能是正常逻辑的退出另外,在 Shell 脚本中,所有条件判断 (比如 if 语句、while 语句) 都以 0 退出状态码表示 True,以非 0 退出状态码为 False。exit 命令exit 命令可用于退出当前 Shell 进程,比如退出当前 Shell 终端、退出 Shell 脚本,等等。exit [N]exit 可指定退出状态码 N,如果省略 N,则默认退出状态码为 0,即表示正确退出。
  • [技术干货] shell脚本体系知识(2)
    变量的运用1. 变量命名界说变量时,变量名不加美元符号($,PHP言语中变量需求),如:your_name="yikoulinux"留神,变量名和等号之间不能有空格,这或许和你了解的悉数编程言语都不相同。一同,变量名的命名须遵从如下规矩:命名只能运用英文字母,数字和下划线,首个字符不能以数字开端。 中心不能有空格,能够运用下划线(_)。 不能运用标点符号。 不能运用bash里的要害字(可用help指令检查保存要害字)。 变量称谓一般习气为大写有用的 Shell 变量名示例如下:RUNOOB LD_LIBRARY_PATH _var var2 无效的变量命名: ?var=123 user*name=runoob2. 常用变量Linux Shell 中的变量分为:体系变量和用户自界说变量。体系变量:HOME、HOME、HOME、PWD、SHELL、SHELL、SHELL、USER 等等比方:echo $HOME 等等..用户自界说变量:界说变量:变量=值 显现当时 shell 中悉数变量:set 吊销变量:unset 变量 声明静态变量:readonly 变量,注意:不能 unset将指令的回来值赋给变量(要害)除了显式地直接赋值,还能够用句子给变量赋值,如:1)A=ls -la反引号,作业里边的指令,并把作用回来给变量 A2)A=$(ls -la)$等价于反引号3)for file in `ls /etc`或for file in $(ls /etc)以上句子将 /etc 下目录的文件名循环出来。3. 举例例1:意义如下:界说一个变量名为name的变量,值为一口linux 输出变量name的值 界说一个变量名为number的变量,初始值为22 输出变量number的值 直接输出带变量的字符串 运用双引号输出带变量的字符串 运用单引号输出带变量的字符串 运用双引号输出带不存在的变量的字符串,不存在的变量默许为空 运用双引号来声明字符串中的变量 运用大括号{&变量名},声明字符串中的变量注意:上述变量是暂时变量,当关闭终端后,变量就会消失。例2:删去变量并检查指定变量unset name 删去变量name检查name变量
  • shell脚本体系知识(1)
    hell 脚本基础Bash 注释Bash 只支持单行注释,使用#开头的都被当作注释语句:# 整行注释 echo hello world # 行尾注释通过 Bash 的一些特性,可以取巧实现多行注释:: ' 注释1 注释2 ' : <<'EOF' 注释1 注释2 EOF ____=' 注释1 注释2Bash 基本数据类型Bash 中基本数据类型只有字符串类型,连数值类型都没有 (declare -i 可强制声明数值类型)。# 都会当作字符串 echo haha echo 1234Bash 字符串串联Bash 中字符串的串联操作,直接将两段数据连接在一起即可,不需要任何操作符。例如:echo "junma""jinlong" echo 1234 5678命令基本知识变量赋值和引用变量a=3 echo $a a="www.junmajinlong.com" echo $a a='hello world' echo $aShell 中可以引用未定义的变量:echo $xyzdefabc可以定义空变量:a= echo $a变量替换变量替换是指在命令开始执行前,Shell 会先将变量的值替换到引用变量的位置处。例如:a="hello" echo $a world在 echo 命令开始执行前,Shell 会取得变量 a 的值 hello,并将它替换到命令行的 $a 处。于是,在 echo 命令开始执行时,命令行已经变成:echo hello world除了变量替换,Shell 还会做其它替换:命令替换进程替换算术运算替换大括号扩展波浪号扩展路径扩展这些扩展和替换,都是 Shell 在调用命令之前就完成的,这和其它语言解析代码的方式不一样。后面会详细解释 Shell 是如何做命令行解析的,如果不掌握命令行解析,当遇到命令行语法错误后很可能会花掉大量无谓的时间去调试命令。而掌握命令行解析后,就会对命令生命周期了如执掌,不敢说一次就能写对所有命令行,但能节省大量调试时间,对写命令行和写脚本的能力也会上升一个层次。
  • [技术干货] CodeArts IDE for RemoteShell快捷键
    CodeArts for RemoteShell区域按键功能全局快捷键Ctrl + Shift + W关闭窗口Ctrl + K组合键基本编辑Ctrl + X剪切Ctrl + C复制Alt + Arrowup向上移动行Alt + Arrowdown向下移动行Shift + Alt + Arrowup在上面复制当前行Shift + Alt + Arrowdown在下面复制当前行Ctrl + Shift + K删除一行Ctrl + Enter在下面插入行Ctrl + Shift + Enter在上面插入行Ctrl + Shift + \跳转到匹配括号Ctrl + ]增加缩进Ctrl + [减少缩进Home转到行首End转到行尾Ctrl + Home转到文件开头Ctrl + End转到文件末尾Ctrl + Arrowup向上滚动行Ctrl + Arrowdown向下滚动行Alt + Pageup向上滚动页面Alt + Pagedown向下滚动页面Ctrl + Shift + [折叠区域Ctrl + Shift + ]展开区域Ctrl + K,Ctrl + [折叠所有子区域Ctrl + K,Ctrl + ]展开所有子区域Ctrl + K,Ctrl + 0折叠所有区域Ctrl + K,Ctrl + J展开所有区域Ctrl + K,Ctrl + C添加行注释Ctrl + K,Ctrl + U删除行注释Ctrl + /切换行注释Shift + Alt + A切换块注释Alt + Z切换自动换行导航Alt + Leftarrow后退Alt + Rightarrow前进查找&替换Ctrl + F查找Ctrl + H替换F3查找下一个Shift + F3查找上一个Alt + Enter选择所有的匹配Ctrl + D将选择添加到下一个查找匹配项Ctrl + K,Ctrl + D将上一个选择移到下一个查找匹配项Alt + C切换是否区分大小写Alt + R切换是否正则表达式Alt + W切换是否全字匹配多光标选择Alt  +  (鼠标点击)插入光标Ctrl  +    Alt  +  ↑在上方插入光标Ctrl  +    Alt  +  ↓在下方插入光标Ctrl  +    U撤消上一个光标操作Shift  +    Alt  +  I在所选的每一行的末尾插入光标Ctrl  +    L选择当前行Ctrl  +    Shift  +  L选择所有当前选择Ctrl  +    F2选择所有出现的当前单词Shift  +    Alt  +  →扩展选择Shift  +    Alt  +  ←收缩选择Shift  +    Alt  +  (拖曳鼠标)列(框)选择Ctrl  +    Shift  +  Alt  +  (箭头键)列(框)选择Ctrl  +    Shift  +  Alt  +  Pageup向前列(框)选择页面Ctrl  +    Shift  +  Alt  +  Pagedown向后列(框)选择页面代码编辑Ctrl + Space显示代码推荐Ctrl + K,Ctrl + X删除每一行行尾空格编辑器editorCtrl + F4,Ctrl + W关闭当前编辑页Ctrl + Shift  + Pageup向左移动编辑器Ctrl + Shift + Pagedown向右移动编辑器Ctrl + \分割编辑器Ctrl + 1 第一编辑器组获取焦点Ctrl + 2第二编辑器组获取焦点Ctrl + 3第三编辑器组获取焦点Ctrl + K,Ctrl + LeftArrow让上一个编辑器组获取焦点Ctrl + K,Ctrl + RightArrow让下一个编辑器组获取焦点Ctrl + K,LeftArrow向左侧移动当前编辑器组Ctrl + K,RightArrow向右侧移动当前编辑器组文件管理Ctrl + S保存文件Ctrl + F4,Ctrl + W关闭文件Ctrl + Shift + T重新打开最近一次关闭的编辑器Ctrl + Tab打开下一个文件Ctrl + Shift + Tab打开上一个文件Ctrl + K,P复制当前活动文件的路径显示F11切换全屏Ctrl + =放大显示Ctrl + -缩小显示Ctrl + B显示/隐藏侧边栏Ctrl + K,Z禅模式,按两次esc退出终端Ctrl + Shift + `创建新终端Ctrl + C复制选择Ctrl + V粘贴到活动终端Ctrl + Arrowup向上滚动Ctrl + Arrowdown向下滚动Shift + Pageup向上滚动页面Shift + Pagedown向下滚动页面Ctrl + Home滚动到顶部Ctrl + End滚动到底部
  • [技术干货] CodeArts IDE for RemoteShell常见问题
    一、登录激活常见问题1、登录华为云失败,该如何处理?解决办法:检查本机是否需要配置proxy登录,如已配置请检查proxy是否有效。在"管理代理服务器"弹窗中配置全局代理,可以成功登录激活RemoteShell。二、proxy配置常见问题1、登录华为云服务器,proxy该如何设置?新建主机连接时,可在"管理代理服务器"弹窗配置。如需修改,可点击修改远程主机信息进行修改。2、proxy配置修改后不生效,如何解决?解决办法:可以尝试点击关闭该主机的所有连接,再重新操作连接。3、proxy配置检查连接失败,如何解决?解决办法:检查proxy的地址和端口是否有效,用户名或密码是否输入错误,修改后重新尝试。三、新建主机连接常见问题1、新建主机连接失败,可根据以下可能原因排查重试。检查用户名、密码是否输入正确。确保SSH服务已开启(默认端口为22),如果修改SSH默认的22端口,请确认要连接的远程端口已配置且生效,并添加对应的防火墙规则。确认当前使用proxy代理配置出口IP的全部地址的远程端口(SSH默认端口为22)已经允许。检查弹性云服务器的防火墙是否允许当前该主机使用的proxy代理配置的出口IP作为入口IP。请确认网络ACL没有禁用当前该主机使用的proxy代理配置的出口IP。2、遇到如下连接失败的场景,该如何解决?在连接远程主机时,遇到如下报错时,即为代理服务器未输入用户名和密码引起。解决办法:需在代理服务器弹窗中输入用户名和密码,如下图:​在连接远程主机时,遇到如下报错时,即为网络超时引起。解决办法:确认proxy地址是否有效。在连接远程主机时,遇到如下报错时,即为错误的密码或主机IP引起。解决办法:修改正确密码后,重新尝试连接。或尝试移除该远程主机后,使用正确的主机地址进行新建远程连接。四、增加用户连接常见问题1、用户尝试打开较多终端时,受到限制?单个用户目前仅支持同时创建7个终端。2、用户名错误导致连接失败,无法修改用户名,如何操作才能连接成功?解决办法:不可直接修改用户名,请移除该用户连接后重新尝试使用正确的用户名新建连接。
  • [技术干货] 使用CodeArts IDE for RemoteShell 连接华为云ECS主机
    简介本章节主要介绍使用RemoteShell插件的远程主机和用户连接、管理代理配置、用户操作远程文件系统及获取华为云服务器相关功能,支持开发者在完全不需要拥有远程开发环境源代码的情况下,也能轻松获得远程开发体验。使用CodeArts IDE for RemoteShell,您可以连接华为云ECS主机或任意主机。一、下载安装CodeArts IDE for Remoteshell现已开放公测,下载获取免费体验。二、创建主机连接RemoteShell支持创建主机(可多台)远程连接,在新建远程连接时,可选择使用或不使用代理进行连接,身份认证支持密码、密钥、双因子三种方式。当RemoteShell自动打开远程主机终端,成功获取远程文件系统时,说明主机连接成功,界面提示如下:在使用过程中,可对远程主机基本信息进行修改,也可以移除主机和断开所有主机连接。三、proxy配置管理可以新增,编辑,删除proxy。如果您需要配置全局代理,可以在“应用程序代理”中进行修改。如果您的远程主机需要使用代理进行连接,只可选用列表中其中一个或不使用代理,即在创建主机连接时选中某个代理或者不使用,或对已有主机信息进行修改。四、增加用户使用连接创建主机连接成功后,会自动增加当前用户的远程使用权限。同时也支持一台主机增加多用户连接。当RemoteShell自动打开远程主机终端,成功获取相应的远程文件系统,说明用户连接成功。在使用过程中,可对用户连接的基本信息进行修改,也可以移除该用户和断开该用户的连接。五、操作远程文件系统和远程终端创建主机连接成功后,即可操作远程文件系统。文件系统通过文件树右键菜单即可对内部文件/文件夹进行上传、下载、复制粘贴、删除、重命名等操作。可直接编辑文件代码,也可通过顶部菜单“编辑文件”功能或编辑区右键菜单进行相关操作。通过文件右键菜单可对文件和终端进行拆分、关闭等操作。与语言服务相关的代码补全、重构、跳转、修复、华为云SDK代码补全助等功能,请您持续关注后续迭代版本。2. 远程终端多终端分区布局:您可以在同一个页面中创建多个RemoteShell终端,并可以直接拖动窗口,随意组合成您喜欢的布局。六、获取华为云服务器首先需要使用华为云账号即可完成登录:2.登录成功后才能获取,绿色表示当前可连接的远程机,点击按钮可以继续执行连接到该主机的操作。
  • [技术干货] 图形化界面安装虚拟机Gtk-WARNING ****cannot open display:
    ssh -Y username@ip的方式登录使用 -Y参数实际上是授权了 X11 转发,远端的 gtk 图形窗口弹出virt-manager如果您的操作系统设置为中文,远端连接过来也会继承这一配置,如果远端没有安装中文字库,窗口显示就会出现乱码使用以下命令,临时将远端服务器的语言配置为英文:export LANG=en_US再次打开窗口发现正常
总条数:136 到第
上滑加载中