跳到主要内容

1、shell语法

更新于:2024年3月21日

shell语法

image-20231023162325946

目录

[toc]

linux中如何把一段shell代码执行结果赋值给变量?

在 Linux 中,你可以使用命令替换(Command Substitution)将一段 shell 代码的执行结果赋值给变量。有两种主要的语法形式用于命令替换:

1、反引号(``)

使用反引号可以将命令的输出嵌套到变量中:

result=`your_shell_command`

例如:

bashcurrent_date=`date`
echo "Today is $current_date"

2、$() 语法

使用 $() 语法也可以实现相同的效果,而且相对更加清晰:

result=$(your_shell_command)

同样的例子:

current_date=$(date)
echo "Today is $current_date"

这两种语法都会执行 your_shell_command,并将其标准输出的结果赋值给 result 变量。

注意事项:

  • 如果你在反引号或 $() 中包含的 shell 命令包含空格或特殊字符最好将整个命令用双引号括起来,以防止意外的解释错误。
  • 在 Bash 中,$() 更常用,而且在嵌套使用时更容易阅读。

例如:

result="$(your_shell_command)"

这样可以确保在命令执行和输出赋值时处理空格等特殊情况更加稳妥。

linux打印变量的方式?

在 Linux 中,你可以使用 echoprintf 命令来打印变量的值。以下是两种常用的方式:

  1. 使用 echo
bashvariable="Hello, Linux!"

echo $variable

或者使用引号:

bashecho "$variable"

echo 命令中,$variable 会被替换为变量的实际值,并打印到标准输出。

  1. 使用 printf
bashvariable="Hello, Linux!"

printf "%s\n" $variable

printf 允许更复杂的格式化,但在简单的情况下,使用 echo 更为常见。

这两种方法都会输出变量的值到终端。选择使用哪一种取决于你的需求,如果只是简单地打印变量的值,通常使用 echo 就足够了。如果需要更复杂的格式化或更精确的控制,可以考虑使用 printf

linux里如何自定义变量

已解决。

2023年10月23日

  • gpt问答

2023年10月23日

在Linux中,可以使用export命令来自定义变量。具体步骤如下:

  1. 打开终端,进入Linux命令行界面。

  2. 输入以下命令来定义变量:

    export 变量名=变量值

    请将"变量名"替换为你想要定义的变量的名称,将"变量值"替换为你想要赋给变量的值。

  3. 如果你想要将变量定义为永久性的,可以将以上命令添加到你的.bashrc.bash_profile文件中。这样,在每次启动终端时,该变量都会自动加载。

例如,要定义一个名为MY_VAR的变量,并将其值设置为Hello World,可以执行以下命令:

export MY_VAR="Hello World"

之后,你就可以在终端中使用$MY_VAR来引用这个变量。例如,可以输入echo $MY_VAR来显示变量的值。

  • 自己测试过程

这里先用本地shell命令查看即可,后期再实现次功能

export hexoMdCounts=`ls  BaiduSyncdisk/source/_posts/ |wc -l`
export counts="当前hexo md文档数量合计: echo ${hexoMdCounts} 个"

echo ${hexoMdCounts}
echo ${counts}


export hexoMdCounts=`ls BaiduSyncdisk/source/_posts/ |wc -l`
export counts="当前hexo md文档数量合计: echo ${hexoMdCounts} 个"

echo ${counts}

image-20231023155340577

shell方式实现过程:

image-20231023160242618

image-20231023160253727

image-20231023160309345

测试效果:

image-20231023160322192

image-20231023160338708

完美,符合预期。😘

shell语法安装软件

image-20230302224953644

(
set -x; cd "$(mktemp -d)" &&
OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
KREW="krew-${OS}_${ARCH}" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
tar zxvf "${KREW}.tar.gz" &&
./"${KREW}" install krew
)

for循环

案例:批量执行命令

for i in {6..20}; do echo 10.130.194.$i ; ssh 10.130.194.$i df -h; echo -e "\n"; done

案例

k=0
for i in {a..l}
do
echo "i am ${i}"
done

或者:
for i in {a..l};do "smartctl -a /dev/sd${i}" |grep -i Serial; done

案例:for循环的脚本如何赋值给一个变量?==(测试成功)==

gpt

for循环的脚本如何赋值给一个变量?

如果你想将包含for循环的脚本赋值给一个变量,你可以使用反引号(``)或$()来执行命令并将其输出赋给变量。这是一个示例:

for i in {1..5}
do
echo "Iteration $i"
done

# 将脚本赋值给变量
script=$(cat <<'END_SCRIPT'
for i in {1..5}
do
echo "Iteration $i"
done
END_SCRIPT
)

# 执行脚本
eval "$script"

在这个例子中,使用cat <<'END_SCRIPT'来创建一个包含多行脚本的文本块。<< 表示Here文档,'END_SCRIPT' 中的单引号使其中的内容被视为纯文本,不进行变量扩展。

然后,使用$(command) 或反引号`` 来执行这个命令并将输出赋给变量 script

最后,你可以使用eval来执行存储在变量中的脚本。请注意,eval可能有一些潜在的安全性问题,因此在使用时要小心。

注意:使用eval来执行脚本是为了将脚本中的变量展开和执行,但这样也可能引入安全问题。确保你的脚本不包含不受信任的输入,以防止潜在的安全风险。


测试过程:

[root@hexo-blog rsync-wiki]# eval "$script"^C
[root@hexo-blog rsync-wiki]# for i in {1..5}
> do
> echo "Iteration $i"
> done
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
[root@hexo-blog rsync-wiki]#
[root@hexo-blog rsync-wiki]# # 将脚本赋值给变量
[root@hexo-blog rsync-wiki]# script=$(cat <<'END_SCRIPT'
> for i in {1..5}
> do
> echo "Iteration $i"
> done
> END_SCRIPT
> )
[root@hexo-blog rsync-wiki]#
[root@hexo-blog rsync-wiki]# # 执行脚本
[root@hexo-blog rsync-wiki]# eval "$script"
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
[root@hexo-blog rsync-wiki]#

while循环

死循环

while true; do echo love; done

案例:如何加一个换行符==(测试成功)==

如何给输出的内容末尾加上一个换行符呢?

  • 案例

如果你想要给输出的内容末尾加上一个换行符,你可以使用 echo 命令,并在输出中添加 -e 选项。以下是一个示例:

[root@hexo-blog linux-test]# echo -e "你的输出内容\n"
你的输出内容

[root@hexo-blog linux-test]#

这个命令中的 -e 选项表示对转义字符进行解释,而 \n 表示换行符。你可以将 "你的输出内容" 替换为实际的输出内容。

  • 案例

如果是在脚本或命令中,你可以在最后一行的输出中使用 echo -e 来确保在末尾添加一个换行符。例如:

[root@hexo-blog linux-test]# ls;echo -e
demo.txt

[root@hexo-blog linux-test]#

这样可以确保 your_command 的输出末尾有一个换行符。

案例:shell报错问题(==已解决==)

$ ssh root@47.97.48.237 cd /root/rsync/site && systemctl reload nginx 这个命令好像有语法错误,请帮我改正下

对于您提供的命令,ssh指令需要将整个远程执行命令部分放在引号里以确保正确执行,尤其是包含了多个命令的情况。请尝试以下形式的命令:

ssh root@47.97.48.237 'cd /root/rsync/site && systemctl reload nginx'

通过将cd /root/rsync/site && systemctl reload nginx部分放在引号中,命令将以整个字符串作为远程执行的命令。这将使您能够先进入指定目录,然后执行systemctl reload nginx命令,而不会遇到语法错误。

6啊😂

image-20230916074007102

案例:配置环境变量以及初始化某个软件的脚本

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

这段代码是什么意思?

这段代码是用于配置环境变量以及初始化 NVM(Node Version Manager)的脚本,让你在任何新的终端会话中都能使用 NVM。具体来说,它做了以下几件事:

  1. export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")":这行代码设定了一个名为 NVM_DIR 的环境变量,它指向 NVM 的安装目录。这里用到了一个条件表达式,检查环境变量 XDG_CONFIG_HOME 是否已设置。如果没有设置(-z "${XDG_CONFIG_HOME-}" 为真),就使用默认的 ${HOME}/.nvm 作为 NVM 的安装目录;如果设置了 XDG_CONFIG_HOME,则使用 ${XDG_CONFIG_HOME}/nvm 作为安装目录。printf %s 是用来确保路径被正确地输出而不解释任何特殊字符。

  2. [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh":这行代码首先检查 nvm.sh 脚本是否存在于上一行指定的 NVM_DIR 目录中,并且文件大小不为零(表示文件确实存在且不为空)。如果这个条件为真(即文件存在且不为空),则执行(source)该脚本。.(或者等价的source命令)用于在当前的 shell 环境中执行 nvm.sh 脚本,这样就可以在任何新的终端会话中使用 NVM 相关的命令了。

简而言之,这段代码确保了每次你打开一个新的终端会话时,NVM 都会被正确初始化,使得你可以使用 NVM 管理 Node.js 版本。


自己测试:

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

#存在
XDG_CONFIG_HOME="/tmp"
/tmp/nvm/nvm.sh

#nvm.sh
#!/bin/bash
echo "i love you ,xyy---tmp"



#不存在
XDG_CONFIG_HOME=
/root/.nvm/nvm.sh


#nvm.sh
#!/bin/bash
echo "i love you ,xyy---root"

image-20240324145055693

测试符合预期。

案例:检查是否为交互式 shell

image-20240728154128846

检查是否为交互式 shell

# 检查是否为交互式 shell
if [[ $- != *i* ]]; then
return
fi
  • 这段代码检查当前shell是否为交互式shell。如果不是交互式shell,脚本会直接返回,避免在非交互式shell环境中执行,从而不会干扰其他服务的正常运行。

详细解释:

这段代码用于检查当前的 shell 是否为交互式 shell。以下是对这段代码的详细解释:

# 检查是否为交互式 shell
if [[ $- != *i* ]]; then
return
fi
  1. $- 变量

    • $- 是一个特殊的 shell 变量,它包含了当前 shell 的选项标志。这些选项标志是在启动 shell 时设置的,或者是在 shell 运行过程中通过 set 命令设置的。
    • 例如,$- 可能包含的选项有 i(交互式)、v(详细模式)、x(追踪模式)等。
  2. [[ ... ]] 条件测试

    • [[ ... ]] 是 Bash 中的一个条件测试结构,用于执行条件判断。
    • $- != *i* 是一个字符串匹配表达式,用于检查 $- 变量中是否包含字符 i
  3. *i* 模式

    • *i* 是一个通配符模式,其中 * 表示任意字符(包括零个字符),i 是要匹配的字符。
    • 因此,$- != *i* 的意思是:如果 $- 变量中不包含字符 i,则条件为真。
  4. if ... then ... fi 结构

    • 如果条件为真(即 $- 变量中不包含字符 i),则执行 then 块中的代码。
    • 在这个例子中,then 块中的代码是 return表示从当前函数或脚本中返回,不再执行后续的代码。
  5. return 命令

    • return 命令用于从当前函数或脚本中退出。如果在一个脚本中使用 return,它会立即停止脚本的执行。

总结

这段代码的目的是确保脚本只在交互式 shell 中运行。如果当前 shell 不是交互式 shell(即 $- 变量中不包含字符 i),脚本会立即返回,不再执行后续的代码。这样可以避免脚本在非交互式环境中(例如在后台任务或某些自动化脚本中)产生不必要的输出或干扰其他进程。

案例:如何远程执行一个shell脚本?-2024.8.17(已解决)

需求

curl -O http://47.100.215.163:6080/public/code/ruyu-blog-install-v4.sh && sh -x ruyu-blog-install-v4.sh

这条命令是从远程服务器下载ruyu-blog-install-v4.sh脚本并执行的,是用来部署一个博客的。
我想实现一个需求:
在执行这条命令后,默认是所有日志都打印在当前终端上,能不能实现如下需求?
1.默认是所有日志都打印在当前终端上
2.同时,把所有日志保存在/root/ruyuy-blog-all.log,把所有报错日志保存在/root/ruyuy-blog-error.log


curl -O http://47.100.215.163:6080/public/code/ruyu-blog-install-v4.sh ; sh -x ruyu-blog-install-v4.sh > >(tee /root/ruyuy-blog-all.log) 2> >(tee /root/ruyuy-blog-error.log >&2)

gpt回答

要实现上述需求,可以通过以下步骤来完成:

  1. 使用 curl 下载脚本。
  2. 使用 sh -x 执行脚本,并将输出日志分别保存到两个文件中。

以下是具体的命令:

# 下载脚本
curl -O http://47.100.215.163:6080/public/code/ruyu-blog-install-v4.sh

# 执行脚本并记录日志
sh -x ruyu-blog-install-v4.sh > >(tee /root/ruyuy-blog-all.log) 2> >(tee /root/ruyuy-blog-error.log >&2)

这里使用了 tee 命令来实现日志的双重输出:

  • > >(tee /root/ruyuy-blog-all.log) 将标准输出(stdout)同时输出到终端和 /root/ruyuy-blog-all.log 文件。
  • 2> >(tee /root/ruyuy-blog-error.log >&2) 将标准错误输出(stderr)同时输出到终端和 /root/ruyuy-blog-error.log 文件。

解释

  • curl -O http://47.100.215.163:6080/public/code/ruyu-blog-install-v4.sh:这条命令从指定的 URL 下载脚本并保存为 ruyu-blog-install-v4.sh 文件。
  • sh -x ruyu-blog-install-v4.sh:这条命令以 debug 模式执行脚本,-x 选项会在执行每一行命令之前打印命令。
  • > >(tee /root/ruyuy-blog-all.log):将标准输出重定向到 tee 命令,通过 tee 命令同时输出到终端和日志文件。
  • 2> >(tee /root/ruyuy-blog-error.log >&2):将标准错误重定向到 tee 命令,通过 tee 命令同时输出到终端和错误日志文件。

这样,所有日志都会打印到终端,同时保存到 /root/ruyuy-blog-all.log,所有报错日志会保存到 /root/ruyuy-blog-error.log

测试

#直接执行如下命令可完成安装ruyu-blog博客的部署
curl -O http://47.100.215.163:6080/public/code/ruyu-blog-install-v2.sh ; sh -x ruyu-blog-install-v2.sh > >(tee /root/ruyu-blog-all.log) 2> >(tee /root/ruyu-blog-error.log >&2)

###输入自己当前服务器的ip,然后坐等部署成功,整个时间预计在12min左右。

效果

image-20240818091616530

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码 x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号 《云原生架构师实战》

image-20230107215126971

🍀 个人博客站点

http://onedayxyy.cn/

image-20231021104335916

image-20231021104405837

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎

https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

image-20231016062113861