标签 脚本 下的文章

Shell 脚本很棒,你可以非常轻松地写出有用的东西来。甚至像是下面这个傻瓜式的命令:

# 用含有 Go 的词汇起名字:
$ grep -i ^go /usr/share/dict/* | cut -d: -f2 | sort -R | head -n1
goldfish

如果用其他编程语言,就需要花费更多的脑力,用多行代码实现,比如用 Ruby 的话:

puts(Dir['/usr/share/dict/*-english'].map do |f|
  File.open(f)
    .readlines
    .select { |l| l[0..1].downcase == 'go' }
end.flatten.sample.chomp)

Ruby 版本的代码虽然不是那么长,也并不复杂。但是 shell 版是如此简单,我甚至不用实际测试就可以确保它是正确的。而 Ruby 版的我就没法确定它不会出错了,必须得测试一下。而且它要长一倍,看起来也更复杂。

这就是人们使用 Shell 脚本的原因,它简单却实用。下面是另一个例子:

curl https://nl.wikipedia.org/wiki/Lijst_van_Nederlandse_gemeenten |
    grep '^<li><a href=' |
    sed -r 's|<li><a href="/wiki/.+" title=".+">(.+)</a>.*</li>|\1|' |
    grep -Ev '(^Tabel van|^Lijst van|Nederland)'

这个脚本可以从维基百科上获取荷兰基层政权的列表。几年前我写了这个临时的脚本,用来快速生成一个数据库,到现在它仍然可以正常运行,当时写它并没有花费我多少精力。但要用 Ruby 完成同样的功能则会麻烦得多。


现在来说说 shell 的缺点吧。随着代码量的增加,你的脚本会变得越来越难以维护,但你也不会想用别的语言重写一遍,因为你已经在这个 shell 版上花费了很多时间。

我把这种情况称为“Shell 脚本编程陷阱”,这是沉没成本谬论的一种特例(LCTT 译注:“沉没成本谬论”是一个经济学概念,可以简单理解为,对已经投入的成本可能被浪费而念念不忘)。

实际上许多脚本会增长到超出预期的大小,你经常会花费过多的时间来“修复某个 bug”,或者“添加一个小功能”。如此循环往复,让人头大。

如果你从一开始就使用 Python、Ruby 或是其他类似的语言来写这个程序,你可能会在写第一版的时候多花些时间,但以后维护起来就容易很多,bug 也肯定会少很多。

以我的 packman.vim 脚本为例。它起初只包含一个简单的用来遍历所有目录的 for 循环,外加一个 git pull,但在这之后就刹不住车了,它现在有 200 行左右的代码,这肯定不能算是最复杂的脚本,但假如我一上来就按计划用 Go 来编写它的话,那么增加一些像“打印状态”或者“从配置文件里克隆新的 git 库”这样的功能就会轻松很多;添加“并行克隆”的支持也几乎不算个事儿了,而在 shell 脚本里却很难实现(尽管不是不可能)。事后看来,我本可以节省时间,并且获得更好的结果。

出于类似的原因,我很后悔写出了许多这样的 shell 脚本,而我在 2018 年的新年誓言就是不要再犯类似的错误了。

附录:问题汇总

需要指出的是,shell 编程的确存在一些实际的限制。下面是一些例子:

  • 在处理一些包含“空格”或者其他“特殊”字符的文件名时,需要特别注意细节。绝大多数脚本都会犯错,即使是那些经验丰富的作者(比如我)编写的脚本,因为太容易写错了,只添加引号是不够的
  • 有许多所谓“正确”和“错误”的做法。你应该用 which 还是 command?该用 $@ 还是 $*,是不是得加引号?你是该用 cmd $arg 还是 cmd "$arg"?等等等等。
  • 你没法在变量里存储空字节(0x00);shell 脚本处理二进制数据很麻烦。
  • 虽然你可以非常快速地写出有用的东西,但实现更复杂的算法则要痛苦许多,即使用 ksh/zsh/bash 扩展也是如此。我上面那个解析 HTML 的脚本临时用用是可以的,但你真的不会想在生产环境中使用这种脚本。
  • 很难写出跨平台的通用型 shell 脚本。/bin/sh 可能是 dash 或者 bash,不同的 shell 有不同的运行方式。外部工具如 grepsed 等,不一定能支持同样的参数。你能确定你的脚本可以适用于 Linux、macOS 和 Windows 的所有版本吗(无论是过去、现在还是将来)?
  • 调试 shell 脚本会很难,特别是你眼中的语法可能会很快变得记不清了,并不是所有人都熟悉 shell 编程的语境。
  • 处理错误会很棘手(检查 $? 或是 set -e),排查一些超过“出了个小错”级别的复杂错误几乎是不可能的。
  • 除非你使用了 set -u,变量未定义将不会报错,而这会导致一些“搞笑事件”,比如 rm -r ~/$undefined 会删除用户的整个家目录(瞅瞅 Github 上的这个悲剧)。
  • 所有东西都是字符串。一些 shell 引入了数组,能用,但是语法非常丑陋和费解。带分数的数字运算仍然难以应付,并且依赖像 bcdc 这样的外部工具($(( .. )) 这种方式只能对付一下整数)。

反馈

你可以发邮件到 [email protected],或者在 GitHub 上创建 issue 来向我反馈,提问等。


via: https://arp242.net/weblog/shell-scripting-trap.html

作者:Martin Tournoij 选题:lujun9972 译者:jdh8383 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在命令行中,使用控制运算符为复合命令添加逻辑。

经常会使用一些简单的复合指令,比如说在一个命令行中连接几个命令。这些命令使用分号分隔,表示一个命令结束。为了在一个命令行中创建一系列简单的 shell 命令,只需要使用分号把每一条命令分隔开,就像下面这样:

command1 ; command2 ; command3 ; command4 ;

最后一个分号你可以不用添加,因为当你按下回车键时就表示一个命令的结束,但是为了和其它的保持一致,还是建议加上比较好。

所有的命令执行都没有什么问题 —— 只要没有什么意外发生。但是当出问题时到底发生了什么呢?我们可以预测,并且通过 Bash 中内置的 &&|| 运算符跟踪这些错误。这两个控制运算符提供了一些流控制,可以让我们改变代码执行队列的顺序。分号和换行符也被认为是 Bash 的控制运算符。

&& 运算符意义简单来说就是“如果 command1 执行成功,就接着执行 command2。”如果 command1 因为任何原因执行失败,那么 command2 将不执行。这个语法看下来像这样:

command1 && command2

这样写是允许的,因为每一个命令都会返回一个值(RC)给 shell 来表示这个命令在执行的过程中是否执行成功或者失败。通常,返回值是 0 表示成功,而一个正数值表示不同种类的错误。有一些系统管理工具仅仅返回一个 1 来表示所有的错误,但是也有很多工具使用其它的正数的返回值来表示各种类型错误。

我们可以很容易的使用脚本来检查 shell 变量 $?,可以通过命令列表中的下一个命令,或者可以直接使用系统管理工具检查。我们一起来看这些返回值。运行一个简单的命令然后立即检查它的返回值,这个返回值始终是属于最后一个运行的命令。

[student@studentvm1 ~]$ ll ; echo "RC = $?"
total 284
-rw-rw-r--  1 student student   130 Sep 15 16:21 ascii-program.sh
drwxrwxr-x  2 student student  4096 Nov 10 11:09 bin
<snip>
drwxr-xr-x. 2 student student  4096 Aug 18 10:21 Videos
RC = 0
[student@studentvm1 ~]$

这个返回值是 0,表示这个命令执行成功了。现在尝试使用同样的命令在一些我们没有权限的目录上。

[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 ~]$

这个返回值的含义可以在 ls 命令的 man 页面 中找到。

现在我们来试试 && 这个控制运算符,因为它也可能会被用在一个命令行程序中。我们将从一个简单的示例开始:创建一个新目录,如果创建成功就在这个目录中创建一个文件。

我们需要一个目录可以创建其它的目录。首先,在你的家目录中创建一个临时的目录用来做测试。

[student@studentvm1 ~]$ cd ; mkdir testdir

~/testdir 中新建一个目录,这也应该是一个空目录,因为是你刚刚创建的,然后创建一个新的空文件在这个新目录中。下面的命令可以做这些事情。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir2 && touch ~/testdir/testdir2/testfile1
[student@studentvm1 ~]$ ll ~/testdir/testdir2/
total 0
-rw-rw-r-- 1 student student 0 Nov 12 14:13 testfile1
[student@studentvm1 ~]$

我们看到一切都运行得很好,因为 testdir 目录是访问且可写的。然后我们改变 testdir 目录的权限,让用户 student 不再具有访问的权限。操作如下:

[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
d---rwxrw-. 3 student student  4096 Nov 12 14:13 testdir
[student@studentvm1 ~]$

在长列表(ll)命令后面使用 grep 命令来列出 testdir 目录。你可以看到用户 student 不再有 testdir 目录的访问权限。现在我们像之前一样运行同样的命令,但是在 testdir 目录中创建的是一个不同的目录。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1
mkdir: cannot create directory ‘/home/student/testdir/testdir3’: Permission denied
[student@studentvm1 ~]$

尽管我们也同样得到了一个错误的消息,但 && 控制运算符阻止了 touch 命令的运行,因为在创建 testdir3 目录的时候发生了错误。通过这种复合的流控制可以阻止一些错误的发生使事情变乱。但是这样看起来变得稍微复杂了一些。

|| 控制运算符允许添加另一个命令,这个命令在初始程序语句返回值大于 0 时执行。

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1 || echo "An error occurred while creating the directory."
mkdir: cannot create directory ‘/home/student/testdir/testdir3’: Permission denied
An error occurred while creating the directory.
[student@studentvm1 ~]$

当我们使用 &&|| 控制运算符时,使用流控制的复合命令的语法格式通常是下面这样的形式。

preceding commands ; command1 && command2 || command3 ; following commands

使用控制运算符的复合命令可以在其它命令之前或者之后,这些和控制运算符流控制有关系,但是不受控制运算符流控制的影响。如果不考虑复合命令的流控制中发生的任何事情那么所有的命令都将执行。

当程序出问题时,这些流控制运算符使得在命令中处理出错和通知我们变得更有效率。我直接在命令行中使用它们,也在脚本中使用。

你可以以 root 用户的身份来删除这个目录和它里面的内容。

[root@studentvm1 ~]# rm -rf /home/student/testdir

你是怎样使用 Bash 控制运算符的呢?在评论区中告诉我们。


via: https://opensource.com/article/18/11/control-operators-bash-shell

作者:David Both 选题:lujun9972 译者:Jamskr 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

你编写或维护过有意义的 bash 脚本吗?如果回答是,那么你可能希望它们以标准且健壮的方式接收命令行参数。Fedora 最近得到了一个很好的附加组件,它可以帮助你生成更好的脚本。不用担心,它不会花费你很多时间或精力。

为什么需要 Argbash?

Bash 是一种解释性的命令行语言,没有标准库。因此,如果你编写 bash 脚本并希望命令行界面符合 POSIXGNU CLI 标准,那么你一般只有两种选择:

  1. 直接编写为脚本量身定制的参数解析功能(可使用内置的 getopts)。
  2. 使用外部 bash 模块。

第一个选项看起来非常愚蠢,因为正确实现接口并非易事。但是,从 Stack OverflowBash Hackers wiki 的各种站点上,它却被认为是最佳选择。

第二个选项看起来更聪明,但使用模块有它自己的问题。最大的问题是你必须将其代码与脚本捆绑在一起。这可能意味着:

  • 要么,你将库作为单独的文件分发
  • 或者,在脚本的开头包含库代码

有两个文件而不是一个是愚蠢的;但采用一个文件的话,会让一堆上千行的复杂代码污染了你的脚本。

这是 Argbash 项目诞生的主要原因。Argbash 是一个代码生成器,它为你的脚本生成一个量身定制的解析库。与其他 bash 模块的通用代码不同,它生成你的脚本所需的最少代码。此外,如果你不需要 100% 符合那些 CLI 标准的话,你可以生成更简单的代码。

示例

分析

假设你要实现一个脚本,它可以在终端窗口中绘制条形图,你可以通过重复一个字符选定的次数来做到这一点。这意味着你需要从命令行获取以下信息:

  • 哪个字符是组成该行的元素。如果未指定,使用破折号 -。 在命令行上,这是个单值定位参数 character,其默认值为 -。(LCTT 译注:定位参数是指确定位置的参数,此处 character 需是命令行的第一个参数)
  • 直线的长度。如果未指定,会选择 80。 这是一个单值可选参数 length,默认值为 80
  • Verbose 模式(用于调试)。 这是一个布尔型参数 verbose,默认情况下关闭。

由于脚本的主体非常简单,因此本文主要关注从命令行获取用户的输入到合适的脚本变量。Argbash 生成的代码会将参数解析结果保存到 shell 变量 _arg_character_arg_length_arg_verbose 当中。

执行

接下来,你还需要 argbash-initargbash bash 脚本,它们是 argbash 包的一部分。因此,运行以下命令:

sudo dnf install argbash

然后,使用 argbash-init 来为 argbash 生成模板,它会生成可执行脚本。你需要三个参数:一个名为 character 的定位参数,一个可选的 length 参数以及一个可选的布尔 verbose。将这些传递给 argbash-init,然后将输出传递给 argbash : `argbash-init --pos character --opt length --opt-bool verbose script-template.sh
argbash script-template.sh -o script
./script`

看到帮助信息了吗?看起来该脚本不知道字符参数的默认选项。因此,看一下 Argbash API,然后通过编辑脚本的模板部分来解决问题:

# ...
# ARG_OPTIONAL_SINGLE([length],[l],[Length of the line],[80])
# ARG_OPTIONAL_BOOLEAN([verbose],[V],[Debug mode])
# ARG_POSITIONAL_SINGLE([character],[The element of the line],[-])
# ARG_HELP([The line drawer])
# ...

Argbash 非常智能,它试图让每个生成的脚本都成为自己的模板,这意味着你不需要存储源模版以供进一步使用,你也不要丢掉生成的 bash 脚本。现在,尝试重新生成如你所预期的下一个线条绘图脚本:

argbash script -o script
./script

如你所见,一切正常。剩下要做的唯一事情就是完成线条绘图功能。

结论

你可能会发现包含解析代码的部分很长,但考虑到它允许你以 ./script.sh x -Vl50 的方式调用,并且能像 ./script -V -l 50 x 一样工作。确实需要一些代码才能做到这一点。

但是,通过调用 argbash-init 并将参数 -mode 设置为 minimal,你可以平衡生成的代码复杂度和解析能力,而转向更简单的代码。这个选项将脚本的大小减少了大约 20 行,这相当于生成的解析代码大小减少了大约 25%。另一方面,full 模式使脚本更加智能。

如果你想要检查生成的代码,请给 argbash 提供参数 -commented,它会将注释放入解析代码中,从而揭示各个部分背后的意图。与其他参数解析库相比较,如 shflags, argsparsebash-modules/arguments,你将看到 Argbash 强大的简单性。如果出现了严重的错误,你需要快速修复解析功能中的一个故障,Argbash 也允许你这样做。

由于你很有可能是 Fedora 用户,因此你可以享受从官方仓库安装命令行 Argbash 的便利。不过,也有一个在线解析代码生成器服务可以使用。此外,如果你在服务器上使用 Docker 工作,你可以试试 Argbash Docker 镜像

这样你可以让你的脚本具有令用户满意的命令行界面。Argbash 随时为你提供帮助,你只需付出很少的努力。


via: https://fedoramagazine.org/improve-bash-scripts-argbash/

作者:Matěj Týč 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

今天,我偶然发现了一组适用于命令行重度用户的实用 BASH 脚本,这些脚本被称为 Bash-Snippets,它们对于那些整天都与终端打交道的人来说可能会很有帮助。想要查看你居住地的天气情况?它为你做了。想知道股票价格?你可以运行显示股票当前详细信息的脚本。觉得无聊?你可以看一些 YouTube 视频。这些全部在命令行中完成,你无需安装任何严重消耗内存的 GUI 应用程序。

在撰写本文时,Bash-Snippets 提供以下 19 个实用工具:

  1. Cheat – Linux 命令备忘单。
  2. Cloudup – 一个将 GitHub 仓库备份到 bitbucket 的工具。
  3. Crypt – 加解密文件。
  4. Cryptocurrency – 前 10 大加密货币的实时汇率转换。
  5. Currency – 货币转换器。
  6. Geo – 提供 wan、lan、router、dns、mac 和 ip 的详细信息。
  7. Lyrics – 从命令行快速获取给定歌曲的歌词。
  8. Meme – 创造命令行表情包。
  9. Movies – 搜索并显示电影详情。
  10. Newton – 执行数值计算一直到符号数学解析。(to 校正:这里不理解)
  11. Qrify – 将给定的字符串转换为二维码。
  12. Short – 缩短 URL
  13. Siteciphers – 检查给定 https 站点启用或禁用的密码。
  14. Stocks – 提供某些股票的详细信息。
  15. Taste – 推荐引擎提供三个类似的项目,如提供物品(如书籍、音乐、艺术家、电影和游戏等。)
  16. Todo – 命令行待办事项管理。
  17. Transfer – 从命令行快速传输文件。
  18. Weather – 显示你所在地的天气详情。
  19. Youtube-Viewer – 从终端观看 YouTube 视频。

作者可能会在将来添加更多实用程序和/或功能,因此我建议你密切关注该项目的网站或 GitHub 页面以供将来更新。

安装

你可以在任何支持 BASH 的操作系统上安装这些脚本。

首先,克隆 git 仓库,使用以下命令:

$ git clone https://github.com/alexanderepstein/Bash-Snippets

进入目录:

$ cd Bash-Snippets/

切换到最新的稳定版本:

$ git checkout v1.22.0

最后,使用以下命令安装 Bash-Snippets:

$ sudo ./install.sh

这将询问你要安装哪些脚本。只需输入 Y 并按回车键即可安装相应的脚本。如果你不想安装某些特定脚本,输入 N 并按回车键。

Do you wish to install currency [Y/n]: y

要安装所有脚本,运行:

$ sudo ./install.sh all

要安装特定的脚本,比如 currency,运行:

$ sudo ./install.sh currency

你也可以使用 Linuxbrew 包管理器来安装它。

安装所有的工具,运行:

$ brew install bash-snippets

安装特定的工具:

$ brew install bash-snippets --without-all-tools --with-newton --with-weather

另外,对于那些基于 Debian 系统的,例如 Ubuntu、Linux Mint,可以添加 PPA 源:

$ sudo add-apt-repository ppa:navanchauhan/bash-snippets
$ sudo apt update
$ sudo apt install bash-snippets

用法

需要网络连接才能使用这些工具。用法很简单。让我们来看看如何使用其中的一些脚本,我假设你已经安装了所有脚本。

1、 Currency – 货币转换器

这个脚本根据实时汇率转换货币。输入当前货币代码和要交换的货币,以及交换的金额,如下所示:

$ currency
What is the base currency: INR
What currency to exchange to: USD
What is the amount being exchanged: 10

=========================
| INR to USD
| Rate: 0.015495
| INR: 10
| USD: .154950
=========================

你也可以在单条命令中传递所有参数,如下所示:

$ currency INR USD 10

参考以下屏幕截图:

Bash-Snippets

2、 Stocks – 显示股票价格详细信息

如果你想查看一只股票价格的详细信息,输入股票即可,如下所示:

$ stocks Intel

INTC stock info
=============================================
| Exchange Name: NASDAQ
| Latest Price: 34.2500
| Close (Previous Trading Day): 34.2500
| Price Change: 0.0000
| Price Change Percentage: 0.00%
| Last Updated: Jul 12, 4:00PM EDT
=============================================

上面输出了 Intel 股票 的详情。

3、 Weather – 显示天气详细信息

让我们查看以下天气详细信息,运行以下命令:

$ weather

示例输出:

正如你在上面屏幕截图中看到的那样,它提供了 3 天的天气预报。不使用任何参数的话,它将根据你的 IP 地址显示天气详细信息。你还可以显示特定城市或国家/地区的天气详情,如下所示:

$ weather Chennai

同样,你可以查看输入以下命令来查看月相(月亮的形态):

$ weather moon

示例输出:

4、 Crypt – 加解密文件

此脚本对 openssl 做了一层包装,允许你快速轻松地加密和解密文件。

要加密文件,使用以下命令:

$ crypt -e [original file] [encrypted file]

例如,以下命令将加密 ostechnix.txt,并将其保存在当前工作目录下,名为 encrypt_ostechnix.txt

$ crypt -e ostechnix.txt encrypt_ostechnix.txt

输入两次文件密码:

Encrypting ostechnix.txt...
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
Successfully encrypted

上面命令将使用 AES 256 位密钥加密给定文件。密码不要保存在纯文本文件中。你可以加密 .pdf、.txt、 .docx、 .doc、 .png、 .jpeg 类型的文件。

要解密文件,使用以下命令:

$ crypt -d [encrypted file] [output file]

例如:

$ crypt -d encrypt_ostechnix.txt ostechnix.txt

输入密码解密:

Decrypting encrypt_ostechnix.txt...
enter aes-256-cbc decryption password:
Successfully decrypted

5、 Movies – 查看电影详情

使用这个脚本,你可以查看电影详情。

以下命令显示了一部名为 “mother” 的电影的详情:

$ movies mother

==================================================
| Title: Mother
| Year: 2009
| Tomato: 95%
| Rated: R
| Genre: Crime, Drama, Mystery
| Director: Bong Joon Ho
| Actors: Hye-ja Kim, Bin Won, Goo Jin, Je-mun Yun
| Plot: A mother desperately searches for the killer who framed her son for a girl's horrific murder.
==================================================

6、 显示类似条目

要使用这个脚本,你需要从这里 获取 API 密钥。不过不用担心,它完全是免费的。一旦你获得 API 密钥后,将以下行添加到 ~/.bash_profileexport TASTE_API_KEY=”你的 API 密钥放在这里”。(LCTT 译注: TasteDive 是一个推荐引擎,它会根据你的品味推荐相关项目。)

现在你可以根据你提供的项目查看类似项目,如下所示:

$ taste -i Red Hot Chilli Peppers

7、 Short – 缩短 URL

这个脚本会缩短给定的 URL。

$ short <URL>

8、 Geo – 显示网络的详情

这个脚本会帮助你查找网络的详细信息,例如广域网、局域网、路由器、 dns、mac 地址和 ip 地址。

例如,要查找你的局域网 ip,运行:

$ geo -l

我系统上的输出:

192.168.43.192

查看广域网 ip:

$ geo -w

在终端中输入 geo 来查看更多详细信息。

$ geo
Geo
Description: Provides quick access for wan, lan, router, dns, mac, and ip geolocation data
Usage: geo [flag]
 -w Returns WAN IP
 -l Returns LAN IP(s)
 -r Returns Router IP
 -d Returns DNS Nameserver
 -m Returns MAC address for interface. Ex. eth0
 -g Returns Current IP Geodata
Examples:
 geo -g
 geo -wlrdgm eth0
Custom Geo Output =>
[all] [query] [city] [region] [country] [zip] [isp]
Example: geo -a 8.8.8.8 -o city,zip,isp
 -o [options] Returns Specific Geodata
 -a [address] For specific ip in -s
 -v Returns Version
 -h Returns Help Screen
 -u Updates Bash-Snippets

9、 Cheat – 显示 Linux 命令的备忘单

想参考 Linux 命令的备忘单吗?这是可能的。以下命令将显示 curl 命令的备忘单:

$ cheat curl

只需用你选择的命令替换 curl 即可显示其备忘单。这对于快速参考你要使用的任何命令非常有用。

10、 Youtube-Viewer – 观看 YouTube 视频

使用此脚本,你可以直接在终端上搜索或打开 YouTube 视频。(LCTT 译注:在媒体播放器中,而不是文本的终端中打开)

让我们来看一些有关 Ed Sheeran 的视频。

$ ytview Ed Sheeran

从列表中选择要播放的视频。所选内容将在你的默认媒体播放器中播放。

要查看艺术家的近期视频,你可以使用:

$ ytview -c [channel name]

要寻找视频,只需输入:

$ ytview -s [videoToSearch]

或者:

$ ytview [videoToSearch]

11、 cloudup – 备份 GitHub 仓库到 bitbucket

你在 GitHub 上托管过任何项目吗?如果托管过,那么你可以随时间 GitHub 仓库备份到 bitbucket,它是一种用于源代码和开发项目的基于 Web 的托管服务。

你可以使用 -a 选项一次性备份指定用户的所有 GitHub 仓库,或者备份单个仓库。

要备份 GitHub 仓库,运行:

$ cloudup

系统将要求你输入 GitHub 用户名, 要备份的仓库名称以及 bitbucket 用户名和密码等。

12、 Qrify – 将字符串转换为二维码

这个脚本将任何给定的文本字符串转换为二维码。这对于发送链接或者保存一串命令到手机非常有用。

$ qrify convert this text into qr code

示例输出:

很酷,不是吗?

13、 Cryptocurrency

它将显示十大加密货币实时汇率。

输入以下命令,然后单击回车来运行:

$ cryptocurrency

14、 Lyrics

这个脚本从命令行快速获取一首歌曲的歌词。

例如,我将获取 “who is it” 歌曲的歌词,这是一首由 迈克尔·杰克逊 Michael Jackson 演唱的流行歌曲。

$ lyrics -a michael jackson -s who is it

15、 Meme

这个脚本允许你从命令行创建简单的表情贴图。它比基于 GUI 的表情包生成器快得多。

要创建一个表情贴图,只需输入:

$ meme -f mymeme
Enter the name for the meme's background (Ex. buzz, doge, blb ): buzz
Enter the text for the first line: THIS IS A
Enter the text for the second line: MEME

这将在你当前的工作目录创建 jpg 文件。

16、 Newton

厌倦了解决复杂的数学问题?你来对了。Newton 脚本将执行数值计算,乃至于符号数学解析。

17、 Siteciphers

这个脚本可以帮助你检查在给定的 https 站点上启用/禁用哪些加密算法。(LCTT 译注:指 HTTPS 通讯中采用的加密算法)

$ siteciphers google.com

18、 Todo

它允许你直接从终端创建日常任务。

让我们来创建一些任务。

$ todo -a The first task
01). The first task Tue Jun 26 14:51:30 IST 2018

要添加其它任务,只需添加任务名称重新运行上述命令即可。

$ todo -a The second task
01). The first task Tue Jun 26 14:51:30 IST 2018
02). The second task Tue Jun 26 14:52:29 IST 2018

要查看任务列表,运行:

$ todo -g
01). The first task Tue Jun 26 14:51:30 IST 2018
02). A The second task Tue Jun 26 14:51:46 IST 2018

一旦你完成了任务,就可以将其从列表中删除,如下所示:

$ todo -r 2
Sucessfully removed task number 2
01). The first task Tue Jun 26 14:51:30 IST 2018

要清除所有任务,运行:

$ todo -c
Tasks cleared.

19、 Transfer

Transfer 脚本允许你通过互联网快速轻松地传输文件和目录。

让我们上传一个文件:

$ transfer test.txt
Uploading test.txt
################################################################################################################################################ 100.0%
Success!
Transfer Download Command: transfer -d desiredOutputDirectory ivmfj test.txt
Transfer File URL: https://transfer.sh/ivmfj/test.txt

该文件将上传到 transfer.sh 站点。Transfer.sh 允许你一次上传最大 10 GB 的文件。所有共享文件在 14 天后自动过期。如你所见,任何人都可以通过 Web 浏览器访问 URL 或使用 transfer 目录来下载文件,当然,transfer 必须安装在他/她的系统中。

现在从你的系统中移除文件。

$ rm -fr test.txt

现在,你可以随时(14 天内)从 transfer.sh 站点下载该文件,如下所示:

$ transfer -d Downloads ivmfj test.txt

获取关于此实用脚本的更多详情,参考以下指南。

获得帮助

如果你不知道如何使用特定脚本,只需输入该脚本的名称,然后按下 ENTER 键,你将会看到使用细节。以下示例显示 Qrify 脚本的帮助信息。

$ qrify
Qrify
Usage: qrify [stringtoturnintoqrcode]
Description: Converts strings or urls into a qr code.
 -u Update Bash-Snippet Tools
 -m Enable multiline support (feature not working yet)
 -h Show the help
 -v Get the tool version
Examples:
 qrify this is a test string
 qrify -m two\\nlines
 qrify github.com # notice no http:// or https:// this will fail

更新脚本

你可以随时使用 -u 选项更新已安装的工具。以下命令更新 “weather” 工具。

$ weather -u

卸载

你可以使用以下命令来卸载这些工具。

克隆仓库:

$ git clone https://github.com/alexanderepstein/Bash-Snippets

进入 Bash-Snippets 目录:

$ cd Bash-Snippets

运行以下命令来卸载脚本:

$ sudo ./uninstall.sh

输入 y,并按下回车键来移除每个脚本。

Do you wish to uninstall currency [Y/n]: y

另请阅读:

好了,这就是全部了。我必须承认,在测试这些脚本时我印象很深刻。我真的很喜欢将所有有用的脚本组合到一个包中的想法。感谢开发者。试一试,你不会失望的。

干杯!


via: https://www.ostechnix.com/collection-useful-bash-scripts-heavy-commandline-users/

作者:SK 选题:lujun9972 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有个简单实用的技巧可以让你的 bash 脚本更稳健 -- 确保总是执行必要的收尾工作,哪怕是在发生异常的时候。要做到这一点,秘诀就是 bash 提供的一个叫做 EXIT 的伪信号,你可以 trap 它,当脚本因为任何原因退出时,相应的命令或函数就会执行。我们来看看它是如何工作的。

基本的代码结构看起来像这样:

#!/bin/bash
function finish {
  # 你的收尾代码
}
trap finish EXIT

你可以把任何你觉得务必要运行的代码放在这个 finish 函数里。一个很好的例子是:创建一个临时目录,事后再删除它。

#!/bin/bash
scratch=$(mktemp -d -t tmp.XXXXXXXXXX)
function finish {
  rm -rf "$scratch"
}
trap finish EXIT

这样,在你的核心代码中,你就可以在这个 $scratch 目录里下载、生成、操作中间或临时数据了。 注1

# 下载所有版本的 linux 内核…… 为了科学研究!
for major in {1..4}; do
  for minor in {0..99}; do
    for patchlevel in {0..99}; do
      tarball="linux-${major}-${minor}-${patchlevel}.tar.bz2"
      curl -q "http://kernel.org/path/to/$tarball" -o "$scratch/$tarball" || true
      if [ -f "$scratch/$tarball" ]; then
        tar jxf "$scratch/$tarball"
      fi
    done
  done
done
# 整合成单个文件
# 复制到目标位置
cp "$scratch/frankenstein-linux.tar.bz2" "$1"
# 脚本结束, scratch 目录自动被删除

比较一下如果不用 trap ,你是怎么删除 scratch 目录的:

#!/bin/bash
# 别这样做!

scratch=$(mktemp -d -t tmp.XXXXXXXXXX)

# 在这里插入你的几十上百行代码

# 都搞定了,退出之前把目录删除
rm -rf "$scratch"

这有什么问题么?很多:

  • 如果运行出错导致脚本提前退出, scratch 目录及里面的内容不会被删除。这会导致资料泄漏,可能引发安全问题。
  • 如果这个脚本的设计初衷就是在脚本末尾以前退出,那么你必须手动复制粘贴 rm 命令到每一个出口。
  • 这也给维护带来了麻烦。如果今后在脚本某处添加了一个 exit ,你很可能就忘了加上删除操作 -- 从而制造潜在的安全漏洞。

无论如何,服务要在线

另外一个场景: 想象一下你正在运行一些自动化系统运维任务,要临时关闭一项服务,最后这项服务需要重启,而且要万无一失,即使脚本运行出错。那么你可以这样做:

function finish {
    # 重启服务
    sudo /etc/init.d/something start
}
trap finish EXIT
sudo /etc/init.d/something stop
# 主要任务代码

# 脚本结束,执行 finish 函数重启服务

一个具体的实例:比如 Ubuntu 服务器上运行着 MongoDB ,你要为 crond 写一个脚本来临时关闭服务并做一些日常维护工作。你应该这样写:

function finish {
    # 重启服务
    sudo service mongdb start
}
trap finish EXIT
# 关闭 mongod 服务
sudo service mongdb stop
# (如果 mongod 配置了 fork ,比如 replica set ,你可能需要执行 “sudo killall --wait /usr/bin/mongod”)

控制开销

有一种情况特别能体现 EXIT trap 的价值:如果你的脚本运行过程中需要初始化一下成本高昂的资源,结束时要确保把它们释放掉。比如你在 AWS (Amazon Web Services) 上工作,要在脚本中创建一个镜像。

(名词解释: 在亚马逊云上的运行的服务器叫“实例”。实例从 亚马逊机器镜像 Amazon Machine Image 创建而来,通常被称为 “AMI” 或 “镜像” 。AMI 相当于某个特殊时间点的服务器快照。)

我们可以这样创建一个自定义的 AMI :

  1. 基于一个基准 AMI 运行一个实例(例如,启动一个服务器)。
  2. 在实例中手动或运行脚本来做一些修改。
  3. 用修改后的实例创建一个镜像。
  4. 如果不再需要这个实例,可以将其删除。

最后一步相当重要。如果你的脚本没有把实例删除掉,它会一直运行并计费。(到月底你的账单让你大跌眼镜时,恐怕哭都来不及了!)

如果把 AMI 的创建封装在脚本里,我们就可以利用 trap EXIT 来删除实例了。我们还可以用上 EC2 的命令行工具:

#!/bin/bash
# 定义基准 AMI 的 ID
ami=$1
# 保存临时实例的 ID
instance=''
# 作为 IT 人,让我们看看 scratch 目录的另类用法
scratch=$(mktemp -d -t tmp.XXXXXXXXXX)
function finish {
    if [ -n "$instance" ]; then
        ec2-terminate-instances "$instance"
    fi
    rm -rf "$scratch"
}
trap finish EXIT
# 创建实例,将输出(包含实例 ID )保存到 scratch 目录下的文件里
ec2-run-instances "$ami" > "$scratch/run-instance"
# 提取实例 ID
instance=$(grep '^INSTANCE' "$scratch/run-instance" | cut -f 2)

脚本执行到这里,实例(EC2 服务器)已经开始运行 注2 。接下来你可以做任何事情:在实例中安装软件,修改配置文件等,然后为最终版本创建一个镜像。实例会在脚本结束时被删除 -- 即使脚本因错误而提前退出。(请确保实例创建成功后再运行业务代码。)

更多应用

这篇文章只讲了些皮毛。我已经使用这个 bash 技巧很多年了,现在还能不时发现一些有趣的用法。你也可以把这个方法应用到你自己的场景中,从而提升你的 bash 脚本的可靠性。

尾注

  • 注1. mktemp 的选项 -t 在 Linux 上是可选的,在 OS X 上是必需的。带上此选项可以让你的脚本有更好的可移植性。
  • 注2. 如果只是为了获取实例 ID ,我们不用创建文件,直接写成 instance=$(ec2-run-instances "$ami" | grep '^INSTANCE' | cut -f 2) 就可以。但把输出写入文件可以记录更多有用信息,便于调试 ,代码可读性也更强。

作者简介:美国加利福尼亚旧金山的作家,软件工程师,企业家。Powerful Python 的作者,他的 blog


via: http://redsymbol.net/articles/bash-exit-traps/

作者:aaron maxwell 译者:Dotcra 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有些误解认为 shell 脚本仅用于 CLI 环境。实际上在 KDE 或 Gnome 桌面下,你可以有效的使用各种工具编写 GUI 或者网络(socket)脚本。shell 脚本可以使用一些 GUI 组件(菜单、警告框、进度条等),你可以控制终端输出、光标位置以及各种输出效果等等。利用下面的工具,你可以构建强壮的、可交互的、对用户友好的 UNIX/Linux bash 脚本。

制作 GUI 应用不是一项困难的任务,但需要时间和耐心。幸运的是,UNIX 和 Linux 都带有大量编写漂亮 GUI 脚本的工具。以下工具是基于 FreeBSD 和 Linux 操作系统做的测试,而且也适用于其他类 UNIX 操作系统。

1、notify-send 命令

notify-send 命令允许你借助通知守护进程发送桌面通知给用户。这种避免打扰用户的方式,对于通知桌面用户一个事件或显示一些信息是有用的。在 Debian 或 Ubuntu 上,你需要使用 apt 命令apt-get 命令 安装的包:

sudo apt-get install libnotify-bin

CentOS/RHEL 用户使用下面的 yum 命令

sudo yum install libnotify

Fedora Linux 用户使用下面的 dnf 命令:

`$ sudo dnf install libnotify`
In this example, send simple desktop notification from the command line, enter:
### 发送一些通知 ###
notify-send "rsnapshot done :)"

示例输出:

 title=

下面是另一个附加选项的代码:

...
alert=18000
live=$(lynx --dump http://money.rediff.com/ | grep 'BSE LIVE' | awk '{ print $5}' | sed 's/,//g;s/\.[0-9]*//g')
[ $notify_counter -eq 0 ] && [ $live -ge $alert ] && { notify-send -t 5000 -u low -i   "BSE Sensex touched 18k";  notify_counter=1; }
...

示例输出:

 title=

这里:

  • -t 5000:指定超时时间(毫秒) (5000 毫秒 = 5 秒)
  • -u low: 设置紧急等级 (如:低、普通、紧急)
  • -i gtk-dialog-info: 设置要显示的图标名称或者指定的图标(你可以设置路径为:-i /path/to/your-icon.png

关于更多使用 notify-send 功能的信息,请参考 man 手册。在命令行下输入 man notify-send 即可看见:

man notify-send

2、tput 命令

tput 命令用于设置终端特性。通过 tput 你可以设置:

  • 在屏幕上移动光标。
  • 获取终端信息。
  • 设置颜色(背景和前景)。
  • 设置加粗模式。
  • 设置反转模式等等。

下面有一段示例代码:

#!/bin/bash

# clear the screen
tput clear

# Move cursor to screen location X,Y (top left is 0,0)
tput cup 3 15

# Set a foreground colour using ANSI escape
tput setaf 3
echo "XYX Corp LTD."
tput sgr0

tput cup 5 17
# Set reverse video mode
tput rev
echo "M A I N - M E N U"
tput sgr0

tput cup 7 15
echo "1. User Management"

tput cup 8 15
echo "2. Service Management"

tput cup 9 15
echo "3. Process Management"

tput cup 10 15
echo "4. Backup"

# Set bold mode
tput bold
tput cup 12 15
read -p "Enter your choice [1-4] " choice

tput clear
tput sgr0
tput rc

示例输出:

 title=

关于 tput 命令的详细信息,参见手册:

man 5 terminfo
man tput

3、setleds 命令

setleds 命令允许你设置键盘灯。下面是打开数字键灯的示例:

setleds -D +num

关闭数字键灯,输入:

setleds -D -num
  • -caps:关闭大小写锁定灯
  • +caps:打开大小写锁定灯
  • -scroll:关闭滚动锁定灯
  • +scroll:打开滚动锁定灯

查看 setleds 手册可看见更多信息和选项 man setleds

4、zenity 命令

zenity 命令显示 GTK+ 对话框,并且返回用户输入。它允许你使用各种 Shell 脚本向用户展示或请求信息。下面是一个 whois 指定域名目录服务的 GUI 客户端示例。

#!/bin/bash
# Get domain name
_zenity="/usr/bin/zenity"
_out="/tmp/whois.output.$$"
domain=$(${_zenity} --title  "Enter domain" \
             --entry --text "Enter the domain you would like to see whois info" )

if [ $? -eq 0 ]
then
  # Display a progress dialog while searching whois database
  whois $domain  | tee >(${_zenity} --width=200 --height=100 \
                    --title="whois" --progress \
                        --pulsate --text="Searching domain info..." \
                                    --auto-kill --auto-close \
                                    --percentage=10) >${_out}

  # Display back output
  ${_zenity} --width=800 --height=600  \
         --title "Whois info for $domain" \
         --text-info --filename="${_out}"
else
  ${_zenity} --error \
         --text="No input provided"
fi

示例输出:

 title=

参见手册获取更多 zenity 信息以及其他支持 GTK+ 的组件:

zenity --help
man zenity

5、kdialog 命令

kdialog 命令与 zenity 类似,但它是为 KDE 桌面和 QT 应用设计。你可以使用 kdialog 展示对话框。下面示例将在屏幕上显示信息:

kdialog --dontagain myscript:nofilemsg --msgbox "File: '~/.backup/config' not found."

示例输出:

 title=

参见 《KDE 对话框 Shell 脚本编程》 教程获取更多信息。

6、Dialog

Dialog 是一个使用 Shell 脚本的应用,显示用户界面组件的文本。它使用 curses 或者 ncurses 库。下面是一个示例代码:

#!/bin/bash
dialog --title "Delete file" \
--backtitle "Linux Shell Script Tutorial Example" \
--yesno "Are you sure you want to permanently delete \"/tmp/foo.txt\"?" 7 60

# Get exit status
# 0 means user hit [yes] button.
# 1 means user hit [no] button.
# 255 means user hit [Esc] key.
response=$?
case $response in
   0) echo "File deleted.";;
   1) echo "File not deleted.";;
   255) echo "[ESC] key pressed.";;
esac

参见 dialog 手册获取详细信息:man dialog

关于其他用户界面工具的注意事项

UNIX、Linux 提供了大量其他工具来显示和控制命令行中的应用程序,shell 脚本可以使用一些 KDE、Gnome、X 组件集:

  • gmessage - 基于 GTK xmessage 的克隆
  • xmessage - 在窗口中显示或询问消息(基于 X 的 /bin/echo)
  • whiptail - 显示来自 shell 脚本的对话框
  • python-dialog - 用于制作简单文本或控制台模式用户界面的 Python 模块

7、logger 命令

logger 命令将信息写到系统日志文件,如:/var/log/messages。它为系统日志模块 syslog 提供了一个 shell 命令行接口:

logger "MySQL database backup failed."
tail -f /var/log/messages
logger -t mysqld -p daemon.error "Database Server failed"
tail -f /var/log/syslog

示例输出:

Apr 20 00:11:45 vivek-desktop kernel: [38600.515354] CPU0: Temperature/speed normal
Apr 20 00:12:20 vivek-desktop mysqld: Database Server failed

参见 《如何写消息到 syslog 或 日志文件》 获得更多信息。此外,你也可以查看 logger 手册获取详细信息:man logger

8、setterm 命令

setterm 命令可设置不同的终端属性。下面的示例代码会强制屏幕在 15 分钟后变黑,监视器则 60 分钟后待机。

setterm -blank 15 -powersave powerdown -powerdown 60

下面的例子将 xterm 窗口中的文本以下划线展示:

setterm -underline on;
echo "Add Your Important Message Here"
setterm -underline off

另一个有用的选项是打开或关闭光标显示:

setterm -cursor off

打开光标:

setterm -cursor on

参见 setterm 命令手册获取详细信息:man setterm

9、smbclient:给 MS-Windows 工作站发送消息

smbclient 命令可以与 SMB/CIFS 服务器通讯。它可以向 MS-Windows 系统上选定或全部用户发送消息。

smbclient -M WinXPPro <<eof
Message 1
Message 2
...
..
EOF

echo "${Message}" | smbclient -M salesguy2

参见 smbclient 手册或者阅读我们之前发布的文章:《给 Windows 工作站发送消息》:man smbclient

10、Bash 套接字编程

在 bash 下,你可以打开一个套接字并通过它发送数据。你不必使用 curl 或者 lynx 命令抓取远程服务器的数据。bash 和两个特殊的设备文件可用于打开网络套接字。以下选自 bash 手册:

  1. /dev/tcp/host/port - 如果 host 是一个有效的主机名或者网络地址,而且端口是一个整数或者服务名,bash 会尝试打开一个相应的 TCP 连接套接字。
  2. /dev/udp/host/port - 如果 host 是一个有效的主机名或者网络地址,而且端口是一个整数或者服务名,bash 会尝试打开一个相应的 UDP 连接套接字。

你可以使用这项技术来确定本地或远程服务器端口是打开或者关闭状态,而无需使用 nmap 或者其它的端口扫描器。

# find out if TCP port 25 open or not
(echo >/dev/tcp/localhost/25) &>/dev/null && echo "TCP port 25 open" || echo "TCP port 25 close"

下面的代码片段,你可以利用 bash 循环找出已打开的端口

echo "Scanning TCP ports..."
for p in {1..1023}
do
  (echo >/dev/tcp/localhost/$p) >/dev/null 2>&1 && echo "$p open"
done

示例输出:

Scanning TCP ports...
22 open
53 open
80 open
139 open
445 open
631 open

下面的示例中,你的 bash 脚本将像 HTTP 客户端一样工作:

#!/bin/bash
exec 3<> /dev/tcp/${1:-www.cyberciti.biz}/80

printf "GET / HTTP/1.0
" >&3
printf "Accept: text/html, text/plain
" >&3
printf "Accept-Language: en
" >&3
printf "User-Agent: nixCraft_BashScript v.%s
" "${BASH_VERSION}"   >&3
printf "
" >&3

while read LINE <&3
do
   # do something on $LINE
   # or send $LINE to grep or awk for grabbing data
   # or simply display back data with echo command
   echo $LINE
done

参见 bash 手册获取更多信息:man bash

关于 GUI 工具和 cron 任务的注意事项

如果你 使用 crontab 来启动你的脚本,你需要使用 export DISPLAY=[用户机器]:0 命令请求本地显示或输出服务。举个例子,使用 zenity 工具调用 /home/vivek/scripts/monitor.stock.sh

@hourly DISPLAY=:0.0 /home/vivek/scripts/monitor.stock.sh

你有喜欢的可以增加 shell 脚本趣味的 UNIX 工具么?请在下面的评论区分享它吧。

关于作者

本文作者是 nixCraft 创始人、一个老练的系统管理员、Linux 操作系统和 UNIX shell 编程培训师。他服务来自全球的客户和不同的行业,包括 IT 、教育、防务和空间探索、还有非营利组织。你可以在 TwitterFacebookGoogle+ 上面关注他。


via: https://www.cyberciti.biz/tips/spice-up-your-unix-linux-shell-scripts.html

作者:Vivek Gite 译者:pygmalion666 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出