https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02
https://www.gnu.org/software/bash/
就是Linux系统的一个外部接口,外壳。
Bash is the GNU Project’s shell—the Bourne Again SHell. This is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and the C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over sh for both programming and interactive use. In addition, most sh scripts can be run by Bash without modification.
使用shell的一个缺点是性能。频繁的调用工具集软件,会导致频繁的文件读取,进程clone,信号处理等等。
导致性能上的损耗。
这个的意识是将脚本的命令,表达式执行都打印到 stderr;
也就是如果想将这个调试信息打印到文件,需要使用 2><file_name>
https://www.runoob.com/w3cnote/linux-shell-brackets-features.html
这个提示的含义是:需要一个单操作数;但是从脚本的意思还是想通过比较变量是否是 “yes"。
is_virtual1=“”
if [ ${is_virtual1} == “yes” ];
then
echo “abc”
fi
a.sh: line 6: [: ==: unary operator expected
https://stackoverflow.com/questions/13617843/unary-operator-expected-error-in-bash-if-condition
如果脚本内容看着没有问题,但是运行的时候,却提示文件没找到,可能的原因是 windows 环境下的字符问题。
使用dos2unix 进行转换脚本文件。或者使用:cat add_ip.sh | tr -d “\r” > add_ip1.sh
https://stackoverflow.com/questions/2637936/ksh-shell-script-wont-execute-and-returns-127-not-found
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/systemtap_beginners_guide/using-usage
You can also instruct stap to run scripts from standard input using the switch -. To illustrate:
Example 2.1. Running Scripts From Standard Input
echo “probe timer.s(1) {exit()}” | stap -
– A – signals the end of options and disables further option processing. Any arguments after the –
are treated as filenames and arguments. An argument of - is equivalent to --.
命令里如果单独出现两个 --, 代表 这个命令的 参数部分已经结束。
可以看 /etc/passwd下的设置
或者通过ps 命令查看 ssh 调用的最终的是哪一个shell
有时候打印使用说明时,会使用下面这种方式,重定向输出到cat,使用 两个! 号作为分割符(可以是任意的字符)
cat << !
${script}: [ -c|-h ] -p <diskpath>
${script}: [ -c|-h ] -d <daemon>
!
If set to a value greater than zero, TMOUT is treated as the default timeout for the read builtin. The select command terminates if input does not arrive after TMOUT seconds when input is coming from a terminal. In an interactive shell, the value is interpreted as the number of seconds to wait for a line of input after issuing the primary prompt. Bash terminates after waiting for that number of seconds if a complete line of input does not arrive.
set -r 之后就出现这个错误;
[root@rhel-cleanmodules ~]# set -r
[root@rhel-cleanmodules ~]# set -ra
[root@rhel-cleanmodules ~]# which set
-bash: /usr/bin/which: restricted: cannot specify `/' in command names
[root@rhel-cleanmodules ~]#
[root@rhel-cleanmodules ~]# which set
-bash: /usr/bin/which: restricted: cannot specify `/' in command names
[root@rhel-cleanmodules ~]# man set
[root@rhel-cleanmodules ~]# which bash
-bash: /usr/bin/which: restricted: cannot specify `/' in command names
4973 rc=$?
4974 if (( ${rc} != 0 )) && (( ${rc} != 1 ))///例子这好个是
4975 then
4974 if (( ${?} != 0 )) && (( ${?} != 1 )) //这里的第二个条件, $?已经发生改变。
4975 then
The braces are reserved words, so they must be separated from the list by blanks or other shell metacharacters. The parentheses are
operators, and are recognized as separate tokens by the shell even if they are not separated
from the list by whitespace.
验证当前的变量函数是否存在
type [-aftpP] name [name …]
With no options, indicate how each name would be interpreted if used as a command name. If the -t option is used, type prints a string which is one of alias, keyword, function, builtin, or file if name is an alias, shell reserved word, function, builtin, or disk file, respectively. If the name is not found, then nothing is printed, and an exit status of false is returned. If the -p option is used, type either returns the name of the disk file that would be executed if name were specified as a command name, or nothing if type -t name would not return file. The -P option forces a PATH search for each name, even if type -t name would not return file. If a command is hashed, -p and -P print the hashed value, which is not necessarily the file that appears first in PATH. If the -a option is used, type prints all of the places that contain an executable named name. This includes aliases and functions, if and only if the -p option is not also used. The table of hashed commands is not consulted when using -a. The -f option suppresses shell function lookup, as with the command builtin. type returns true if all of the arguments are found, false if any are not found.
type func &>/dev/null
if (( $? != 0 )); then
name=(“Linux Handbook” “It’s FOSS”)
echo “Hello ${name[1]}!”
${parameter:-word} uses word as the default if the parameter is unset.
https://stackoverflow.com/questions/40230008/whats-the-usages-of-hyphen-in-linux-shell
${variable:+string}如果variable有值,就用string,和减号相反。
${#variable}
#Capitalizes
${variable^}
${variable^^}
#Lowercases
${variable,}
${variable,}
If ‘|&’ is used, command1’s standard error, in addition to its standard output, is connected to command2’s standard input through the pipe; it is shorthand for 2>&1 |. This implicit redirection of the standard error to the standard output is performed after any redirections specified by the command.
If a command is terminated by the control operator ‘&’, the shell executes the command asynchronously in a subshell.
The character ‘~’ at the beginning of a file name also has special significance. If alone, or followed by a slash, it represents your home directory. For example ~/bin expands to /home/you/bin. If the ‘~’ is followed by a word, the string represents the home directory of the user named by that word. For example ~john/bin expands to /home/john/bin.
表示所有的参数。
在shell里,星号匹配任意字符;正则表达式里表示个数,之前表达式匹配的个数,可以用来匹配零个或者多个星号之前的字符表达式。You may be familiar with * as a shell metacharacter, where it means “zero or more characters.”
但是shell里的星号和正则表达式里的含义完全不一样。
举例;匹配字符串:
# Update PATH
if [[ ${PATH} != *${tmp_upd_sbin_dir}* ]]; then
export PATH=${tmp_upd_sbin_dir}:${PATH}
fi
The “>” redirection operator truncates the file before the shell does anything else;重新生成文件
是append,续接
eval [arg …]
The args are read and concatenated together into a single command. This command is then read and executed by the shell, and its exit status is returned as the value of eval. If there are no args, or only null arguments, eval returns 0.
eval 返回命令执行的返回值。
重新设置参数。
set [–abefhkmnptuvxBCEHPT] [-o option-name] [arg …]
set [+abefhkmnptuvxBCEHPT] [+o option-name] [arg …]
Without options, the name and value of each shell variable are displayed in a format that can be reused as input for setting or
resetting the currently-set variables. Read-only variables cannot be reset. In posix mode, only shell variables are listed. The
output is sorted according to the current locale. When options are specified, they set or unset shell attributes. Any arguments
remaining after option processing are treated as values for the positional parameters and are assigned, in order, to $1, $2, …
$n. Options, if specified, have the following meanings:
-a Automatically mark variables and functions which are modified or created for export to the environment of subsequent cmmands.
-b Report the status of terminated background jobs immediately, rather than before the next primary prompt. This is effective
only when job control is enabled.
<lc-a:root>/root:
# set a=b c d
<lc-a:root>/root:
# echo $1
a=b
<lc-a:root>/root:
# echo $2
c
! Expands to the process ID of the job most recently placed into the background, whether executed as an asynchronous command or using the bg builtin (see JOB CONTROL below).
0是命令行的第一个参数,也就是执行的命令,获取命令里的文件名,不带路径信息
相对的有 ${0%/*},这个是获取命令的路径;
例子:
<a:root>/root:
# cat a.sh
#!/bin/ksh
echo ${0##*/}
echo ${0%/*}
<a:root>/root:
# ./a.sh
a.sh
. ### ${0%/*}
<a:root>/root:
# /root/a.sh
a.sh
/root #### ${0%/*}
${parameter%%word}
${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the %'' case) or the longest matching pattern (the
%%‘’ case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
blkid -s UUID -o value
if ! mkdir -p /tmp/abc /tmp/cde/ /tmp/sdf
then
fi
newgrp
newgrp - log in to a new group
[root@rhel-cleanmodules sbc]# man rev
[root@rhel-cleanmodules sbc]# echo “abced” |rev
decba
if [[ ${filename} == *"abc"* ]]; then
continue;
fi
[root@rhel-cleanmodules sbc]# which tac
/usr/bin/tac
[root@rhel-cleanmodules sbc]# rpm -qf /usr/bin/tac
coreutils-8.30-8.el8.x86_64
迭代修改权限
echo “abc\c”, 末尾加\c
<-a:root>/root:
/usr/bin/dirname
<-a:root>/root:
:rpm -qf /usr/bin/dirname
coreutils-8.30-8.el8.x86_64
!$ ---- 上次命令的执行结果;
man 2 read, 找到 read的帮助文档在第二部分; 系统调用
man 1 read, 1 for the command. 第一部分是关于命令
1 Executable programs or shell commands
2 System calls (functions provided by the kernel)
3 Library calls (functions within program libraries)
4 Special files (usually found in /dev)
5 File formats and conventions eg /etc/passwd
6 Games
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
8 System administration commands (usually only for root)
9 Kernel routines [Non standard]
dmesg: print or control the kernel ring buffer, 只是查看内存中缓存的log,如果缓存被覆盖之后,就看不到了。所以我们可以根据有没有启动参数command 行来确定dmesg是否有丢的情况。
ps 命令,就是读取/proc目录下的内容
free
[root@localhost grub2]# free
total used free shared buff/cache available
Mem: 1873316 176708 1313896 8636 382712 1542800
Swap: 2170876 0 2170876 ///交互分区,是在硬盘上分配的空间,给kernel使用,当内存不够用时,可以将一部分内存放到磁盘交互分区上去。 一般情况下这个swap的使用情况应该时0,如果被使用很多的话说明系统需要做一下优化。
strace date |& grep read
That’s because strace prints it’s output on standard error and the pipe symbol is only grabbing standard out.
But in bash if you do |&, right next to each other. Then shell will arrange for both standard output and standard error to go into pipe.
cd 这个命令有点特殊,系统里没有binary与之对应;这个不是正规的Linux 命令,一般的命令会启动一个process来完成相应的认为,而cd的作用是更改当前进程的工作目录,也就是shell的工作目录,shell进程负责解释cd命令并调用chdir系统函数来更改路径。
crw-rw-rw-. 1 root root 1, 7 Jan 26 09:29 full /// 第一个字母c,代表character 设备 Documents/admin-guide/devices.txt
brw-rw----. 1 root disk 8, 0 Jan 26 09:29 sda ///第一个字母b,代表block设备
brw-rw----. 1 root disk 8, 1 Jan 26 09:29 sda1
brw-rw----. 1 root disk 8, 2 Jan 26 09:29 sda2
fdisk -l ,起始时读的文件/sys/dev/block/下面的文件来列出磁盘的情况
Linux 系统启动顺序:Power on,开机自检-> BIOS->如果选择磁盘启动,BIOS会到特定的磁盘位置找到Grub的启动点-> GRUB boot loader-> GRUB 根据配置找到linux kernel image,启动kernel-》然后再是kernel的启动顺序。->调用init 调用systemctl相关的服务进程
man -K grub
NAME
grub-editenv — Manage the GRUB environment block.
SYNOPSIS
grub-editenv [-v | --verbose] [FILE]
<create | list | set NAME=VALUE | unset NAME>
DESCRIPTION
grub-editenv is a command line tool to manage GRUB's stored environment.
OPTIONS
--verbose
Print verbose messages.
FILE
File name to use for grub environment. Default is /boot/grub/grubenv .
COMMANDS
create
Create a blank environment block file.
list
List the current variables.
set [NAME=VALUE ...]
Set variables.
unset [NAME ...]
Delete variables.
SEE ALSO
info grub
cpio - copy files to and from archives
make help, 可以查看Makefile 提供的编译选项
#!/bin/bash
file=/etc/resolv.conf
while IFS= read -r line; do
# echo line is stored in $line
echo $line
done < "$file"
pid=$(< ${PIDFILE})
line1=echo ${line}|awk '{print tolower($0)}'
输入字符到action
case $Action in
"e" | "E")
echo "You decided to exit."
exit 1
;;
"1")
echo "You selected 1"
break
;;
"2")
echo "You selected 1"
break
;;
*)
;;
esac # 结束
if [[ ! -z $temp ]] ; then
fi
if [[ ! -f “${file}” ]]; then
archive_zip=$(eval ${cmd})
archive=·cmd·
unzip -j file -d dir
cut -d’:’ -f2
/bin/sed ‘s/[[:space:]]//g’
sed -i “/log_path/c $logpath” ansible.cfg
-i edit files in place (makes backup if SUFFIX supplied)
c
text Replace the selected lines with text, which has each embedded newline preceded by a backslash.
sed -e ‘s/1//’ -e 's/[ \t].
/
/
′
替换首尾空格
t
a
b
成空
∣
s
e
d
′
s
/
[
:
]
∗
/
′
//' 替换首尾空格tab 成空 | sed 's/[^:]*/'
//′替换首尾空格tab成空∣sed′s/[:]∗/′platform_type’/'2 |
sed ‘s/:{1}/& /g’` 替换一个冒号,成冒号加空格
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
sed s:${xmlpath}/::
echo -e “
(
d
a
t
e
)
:
"
"
(date): " "
(date):""{@}” >> “${log_file}” // $@
$# 参数个数
-e enable interpretation of backslash escapes
date +%T — 22:23:46
( p r i n t f m e d i a (printf media%02d " (printfmediaid")
MAX_WAIT=
(
(
420
/
30
)
)
啊
(( 420 / 30 )) 啊
((420/30))啊(echo “2^8-1” |bc) 计算 2的8次方减1.
printf ‘%x\n’ $a // 转换16进制
pids=($(jobs -l % | grep -E -o '^(\[[0-9]+\]\+| ) [ 0-9]{5} ' | sed -e 's/^[^ ]* \+//' -e 's! $!!'))
PIDS[${NAME}]=${pids[0]}
while [ 1 ]
do
done
for (( i=0; i < MAX_WAIT; i++))
do
# Need to wait for
kill -0 "${pids[0]}" 2>/dev/null
ret=$?
if [[ "${ret}" != "0" ]]; then
break
fi
sleep 30
done
for MAP in /sys/firmware/memmap/* ; do echo “$(cat $MAP/start) - $(cat
M
A
P
/
e
n
d
)
(
MAP/end) (
MAP/end)((cat $MAP/type))” ; done
遍历文件;
-z string
True if the length of string is zero.
string
-n string
True if the length of string is non-zero.
if [[ ${rpm_file} == debuginfo ]] 字符串比较
if [[ $# -le 2 ]]; then
if [[ $# -eq 0 ]]
if [[ -n $aa ]]; then
CONDITIONAL EXPRESSIONS
Conditional expressions are used by the [[ compound command and the test and [ builtin commands to test file attributes and perform string and arithmetic comparisons. Expressions are formed from the following unary or
binary primaries. If any file argument to one of the primaries is of the form /dev/fd/n, then file descriptor n is checked. If the file argument to one of the primaries is one of /dev/stdin, /dev/stdout, or /dev/stderr,
file descriptor 0, 1, or 2, respectively, is checked.
Unless otherwise specified, primaries that operate on files follow symbolic links and operate on the target of the link, rather than the link itself. When used with [[, the < and > operators sort lexicographically using the current locale. The test command sorts using ASCII ordering.
-a file
True if file exists.
-b file
True if file exists and is a block special file.
-c file
True if file exists and is a character special file.
-d file
True if file exists and is a directory.
-e file
True if file exists.
-f file
True if file exists and is a regular file.
-g file
True if file exists and is set-group-id.
-h file
True if file exists and is a symbolic link.
-k file
True if file exists and its ``sticky'' bit is set.
-p file
True if file exists and is a named pipe (FIFO).
-r file
True if file exists and is readable.
-s file
True if file exists and has a size greater than zero.
-t fd True if file descriptor fd is open and refers to a terminal.
-u file
True if file exists and its set-user-id bit is set.
-w file
True if file exists and is writable.
-x file
True if file exists and is executable.
-G file
True if file exists and is owned by the effective group id.
-L file
True if file exists and is a symbolic link.
-N file
True if file exists and has been modified since it was last read.
-O file
True if file exists and is owned by the effective user id.
-S file
True if file exists and is a socket.
file1 -ef file2
True if file1 and file2 refer to the same device and inode numbers.
file1 -nt file2
True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
file1 -ot file2
True if file1 is older than file2, or if file2 exists and file1 does not.
-o optname
True if the shell option optname is enabled. See the list of options under the description of the -o option to the set builtin below.
-v varname
True if the shell variable varname is set (has been assigned a value).
-z string
True if the length of string is zero.
string
-n string
True if the length of string is non-zero.
string1 == string2
string1 = string2
True if the strings are equal. = should be used with the test command for POSIX conformance.
string1 != string2
True if the strings are not equal.
string1 < string2
True if string1 sorts before string2 lexicographically.
string1 > string2
True if string1 sorts after string2 lexicographically.
arg1 OP arg2
OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respec‐
tively. Arg1 and arg2 may be positive or negative integers.
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
if egrep -q “aa” <file_name> > /dev/null 2>&1
then
elif
fi
[[ “ A C T I O N " = = " 11 " ∣ ∣ " {ACTION}" == "11" || " ACTION"=="11"∣∣"{ACTION}” == “22” ]]
parse_opts "$@"
parse_opts function
typeset opt_spec arg
# Define the arguments
opt_spec=":"
opt_spec+="[-][a:-action]: "
opt_spec+="[-][93:-nockpt] "
opt_spec+="[-][94:-step]: "
opt_spec+="[-][95:-toload]: "
opt_spec+="[-][96:-tkey]: " /// 前有-,或者没有,
opt_spec+="[-][97:-fturl]: "
opt_spec+="[-][98:-examples] "
opt_spec+="[-][h:-help] "
# parse command-line
while getopts "${opt_spec}" arg ; do
case "${arg}" in
98) # --examples
print "${GENERAL_USAGE}\n${EXAMPLES}"
scriptexit "${CURR_CMD}" 0
;;
97) # --fturl
fturl.found=1
fturl.value="${OPTARG}"
;;
action=( found=0; value=“” )
action.found=1
action.value=“${OPTARG}”
curl -s -S -O url
shift [n]
The positional parameters from n+1 … are renamed to $1 … Parameters represented by
the numbers $# down to $#-n+1 are unset. n must be a non-negative number less than or
equal to $#. If n is 0, no parameters are changed. If n is not given, it is assumed to
be 1. If n is greater than $#, the positional parameters are not changed. The return
status is greater than zero if n is greater than $# or less than zero; otherwise 0.
if (( ${#*} < 1 )); then
logger - a shell command interface to the syslog(3) system log module
logger -t ${tag}
l
o
g
o
p
t
"
{logopt} "
logopt"{msg}"
logopt=“-s -p local3.error”
-t, --tag tag
Mark every line to be logged with the specified tag. The default tag is
the name of the user logged in on the terminal (or a user name based on
effective user ID).
for word in ${line}
首先创建一个数组 array=(a b word) 和一句话的作用相同
for element in ${array[@]}
do
echo $element
done
(( cnt++ ))
tr - translate or delete characters
tr ‘\n’ ’ ’ //替换 换行到空格
使用xargs 将字符串换行,按照空格隔开
pgrep -d " " name //用空格分开
ps -e -o pid,cmd
taskset -p ${mask} ${vm_pid}
taskset is used to set or retrieve the CPU affinity of a running process given its pid, or to launch a new
command with a given CPU affinity. CPU affinity is a scheduler property that “bonds” a process to a given set
of CPUs on the system. The Linux scheduler will honor the given CPU affinity and the process will not run on
any other CPUs. Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to
keep processes on the same CPU as long as practical for performance reasons. Therefore, forcing a specific
CPU affinity is useful only in certain applications.
hostname
runcon -u system_u -r system_r
$$
IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ``‘’.
默认的内部分割符。
根据手动的signal,信号,执行一些操作。
trap “rm -f ${LOCK_FILE};return 1” 1 2 15
./add_subnet.sh: line 61: syntax error at line 67: `}’ unexpected
这里是说大括号,不太正常,
出现这个错误的一种情况:
echo "success add ${}" # 忘记写参数名称。
这个错误的意思是,语法错误,期望“end of file”标识。
出现的一种情况
commit_subnet() ## 调用shell 函数时,使用了括号
可能的原因是参数使用(展开)时,使用了小括号而不是大括号。
$(subnetnum)
${subnetnum}
这两个的区别,第一个是执行subnetnum命令;
第二个是参数subnetnum的展开。
#!/bin/ksh
total=2048
interval=500
(( remain = total % interval ))
(( loop = total / interval + 2 ))
for (( i=1; i < loop; i++))
do
(( start = ( i - 1 ) * 500 + 1))
if (( i == ( loop - 1 ) ))
then
(( interval = remain ))
fi
python a.py ${start} ${interval}
if [[ $? != 0 ]]; then
echo "generate file failure ${i}"
exit 1
fi
/opt/bin/xml2cfg -h $(/opt/bin |awk '{print $1}') -p 9650 -i publish_realm${start}.xml -o batch.out
if [[ $? != 0 ]]; then
echo "import configure failure ${i}"
exit 2
fi
grep -q "Error" batch.out
if [[ $? == 0 ]]; then
echo "checkout result failure ${i}"
echo "please check the batch.out file for detail error"
exit 3
fi
echo "import success for${i}, at $(date)"
done
# if the device exist, then execute following command to add vlan interface;
# and gateway ip
ip link show dd
if [[ $? == 0 ]]; then
for (( i=1;i<2049;i++ ))
do
ip link add link dd name dd.${i} type vlan protocol 802.1Q id ${i}
ip link set dev dd.${i} up
done
for (( i=1;i<2049;i++ ))
do
subnet=$(ip addr show dup1.$i | grep "10.87" | awk -F'.' '{print $3}')
if [[ ! -z $subnet ]]; then
ip addr add 10.87.${subnet}.254 dev dd.${i}
fi
done
else
echo "there is no device for dd"
fi
对于bash 和 ksh,执行格式错误的可执行文件的错误提示不一样:
sh: /home/mzhan017/bin/tar: cannot execute binary file
ksh:/home/mzhan017/bin/tar.bak: /home/mzhan017/bin/tar.bak: cannot execute [Exec format error] 、、 这个提示的更明确一些。
\t ↩︎