命令行安全技巧[关闭]


34

命令行和脚本编写很危险。使用rm -rf进行一些错字操作,您就陷入了痛苦的世界。在运行导入脚本的同时,将prod与数据库名称中的stage混淆,您会陷入困境(如果它们位于同一台服务器上,那不好,但是会发生)。同样,为时已晚,您发现撒入的服务器名称与您在执行一些命令后认为的名称不同时,已经太晚了。您必须尊重Hole Hawg

在运行有风险的命令之前,我有一些习惯-例如对我所在的服务器进行三重检查。这是一篇有关rm安全有趣文章

哪些小礼节,工具和技巧可以使您在命令行上保持安全?我的意思是客观的东西,例如“先运行ls foo *,查看其输出,然后用rm -rf替换ls,以避免运行rm -rf foo *或类似的东西”,而不是“确保您知道命令会执行”。


3
+1表示“开始时是命令行” cryptonomicon.com/command.zip
艾利·佩恩

这不是社区Wiki的问题吗?不会有一个权威或完整的答案。
比尔·魏斯

Answers:


45

一种有效的方法是在外壳上使用不同的背景色进行生产/登台/测试服务器。


6
是的,每当有root特权时,也要使用明亮的尖叫红色或橙色。
亚当·达米科

1
有什么方法可以自动将远程机器终端的颜色设置为与您登录时不同的颜色?使用Gnome-也许这应该是一个单独的问题。
乔纳

2
只要有一个switch语句,即可根据计算机的主机名更改PS1变量。
尼尔

2
对于任何Windows人士而言,Sysinternals都有这颗宝石,它将在墙纸上突出显示主机信息。 technet.microsoft.com/en-us/sysinternals/...
squillman

是是是-我的生产iSeries会话现在变成红色白色,以防止出现以下情况:pwrdwnsys选项(* IMMED)重新启动(* YES)
Peter T. LaComb Jr.

14

开始之前,请牢记一个退出计划。

  • 压缩文件/目录,而不是立即删除
  • 将(cisco)路由器设置为在'x'分钟内重新启动,并且不要立即'wr'
  • 确保您要更改的界面不是您输入系统所用的界面。这可以是您远程登录到的路由器接口,也可以是VNC连接到的以太网端口。
  • 永远不要以“ root”身份登录
  • 进行备份。检查它是否好。再做一个。
  • 问一个你信任的人,“我要在这里做些蠢事吗?”

3
+1 cisco ios在确定其有效之前不会保存。该死的我记得Amiga时代,所有的操作系​​统对话框都有“使用”,“保存”和“取消”-其中“使用”将仅应用设置,而不保存它们以供下次重启。那非常有用!
奥斯卡(Oskar Duveborn)

我想今天有一个更好的解决方案是对所有系统更改进行无限制的撤消-这样您就更安全了。当然,如果您更改的设置使系统撤消功能无法使用,那么您还是会被搞砸。.hmm ^^
Oskar Duveborn

1
+1表示“重新载入5”。当ACL更改将我从远程路由器/交换机中锁定时,救了我的屁股多次。
格雷格(Greg Work)2009年

最后一点+1-健全性检查。容易做到,然后至少您有两个对既得利益感兴趣的人来解决出现的任何问题;)
Ashley

10

我对其中一些问题有低技术含量的解决方案。

我已经养成了以下习惯(在计划以root身份工作时):

  • 首先,以普通用户身份登录,然后使用sudo su - root切换到root用户。我这样做是出于心理准备,提醒我,我已经精神上走进了一个非常危险的区域,应该时刻保持警惕和警惕。听起来很有趣,但仅通过一点一点强调我就不会粗心大意,这个小小的仪式就为我节省了很多悲痛。
  • 键入每个命令,但从按下[Return]键。 从不
  • 没有确切地了解命令的作用,就不会执行任何命令。 如果您不知道该怎么做,那么您正在使用系统玩俄罗斯轮盘
  • 按下[Return]键之前,请仔细检查CLI上敲出的命令。如果有任何犹豫,任何潜在问题的提示,将再次进行检查。如果这种犹豫仍然存在,该命令将保留在该行上,然后我将F2转到另一个控制台以查阅手册页等。如果在图形会话中,我将启动浏览器并进行一些搜索。
  • 没有任何普通用户sudo使用我的系统,这不是因为我是BOFH,而是因为没有进行准备和培训,这就像给猴子装了枪。刚开始有趣而有趣,直到猴子低头看着桶并挤压...

使用rm时,我总是cd先进入目录,然后使用前缀./以确保目录正确,即

cd /usr/some/directory ; rm ./targetfile

或者我指定文件的完整路径

rm /usr/some/directory/targetfile

这是一个PITA,但是...总比后悔好。


1
我只为预先选择的命令列表提供sudo,例如apache2 reload。否则,用户必须经过我。这是痛苦的事情,但这是为15个人运行devbox的最佳防御。
Artem Russakovskii 09年

2
Quote:“但是因为没有进行准备和训练,这就像给猴子装了枪。一开始它很有趣,直到猴子低头看着桶并挤压……”实际上,在那之后,它仍然很有趣。 ..只是相当混乱
Mikeage

您应该使用sudo -i而不是sudo su,通常使用sudo运行特定命令会更安全一些。
LapTop006 2009年

如果您从未按过回车键,该如何执行命令?
g。

1
&& 是你的朋友!而不是cd / usr / some / directory; rm ./targetfile您应该cd / usr / some / directory && rm ./targetfile这样,如果cd失败,您将永远不会在原始目录中结束rm'ing targetfile。不过,执行全路径rm更好。
Mike G.

10

这是Windows Powershell特有的。

作为策略,我们在每台服务器上添加以下计算机profile.ps1。这确保满足以下条件:

  1. 管理员Powershell控制台窗口具有深红色背景色
  2. 管理员已添加到标题
  3. 消息“警告:Powershell正在以管理员身份运行”。在启动时写的
  4. 标题栏的前缀为“管理员:”
  5. 标准实用程序(如公司shell脚本,vim和infozip)位于路径中。
$ currentPrincipal =新对象Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity] :: GetCurrent())
&{
    如果($ currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole] :: Administrator))
    {
        (获取主机)。UI.RawUI.Backgroundcolor=“ DarkRed”
        清除主机
        写主机“警告:PowerShell以管理员身份运行。
    }

    $实用程序= $ null
    if([IntPtr] :: size * 8 -eq 64)
    {
        $ host.UI.RawUI.WindowTitle =“ Windows PowerShell(x64)” 
        $ utilities =“ $ {env:programfiles(x86)} \ Utilities”
    }
    其他
    {
        $ host.UI.RawUI.WindowTitle =“ Windows PowerShell(x86)”
        $ utilities =“ $ {env:programfiles} \ Utilities”
    }
    if((测试路径$ utilities)-和!($ env:path -match $ utilities.Replace(“ \”,“ \\”))))
    {
        $ env:path =“ $ utilities; $ {env:path}”
    }
}

功能提示
{
    如果($ currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole] :: Administrator))
    {
        if(!$ host.UI.RawUI.WindowTitle.StartsWith(“ Administrator:”)))
        {$ Host.UI.RawUI.WindowTitle =“管理员:” + $ host.UI.RawUI.WindowTitle}
    }
    'PS'+ $(如果(($ nestedpromptlevel -ge 1){'>>'})+'>'
}

太酷了-我希望您可以轻松地在所有服务器上的linux中执行类似的操作。
詹森(Jason Tan)

1
在powershell中,这是通过编辑$ pshome / profile.ps1(机器配置文件)完成的。为什么不能在/etc/.bash_profile中的Linux上做等效的事情?
Brian Reiter 2009年

2
将$ ConfirmPreference更改为“ medium”(默认为“高”)也很有用,更多的内容将提示您进行确认。
理查德

6

我可以同意上述所有答案,但我必须强调这一非常非常重要的技巧:

知道何时避免多任务。


5

我确保正在使用的系统的主机名位于bash(或其他shell)提示符下。如果我被chroot,我也要确保它也在那里。

我曾经在另一个实时Linux发行版中安装Gentoo系统,却rm在错误的外壳中意外地运行了一个破坏性的命令(不记得它是ATM-的某种变体),导致实时系统上出现了很多东西删除,而不是从chroot内部删除。从那时起,我一直

export PS1="(chroot) $PS1"

每当我在chroot中工作时。


1
+1-同样,在提示中保留当前工作目录(如果正在深度嵌套的文件系统中,则为最后n层)也很有帮助。
穆拉里·苏里雅尔

官方的Gentoo手册恰恰表明了这一点,当从实时CD切换到新创建的Gentoo时!
cd1

CD1:是的,但是x86快速安装指南(gentoo.org/doc/en/gentoo-x86-quickinstall.xml)却没有,这就是我当时所使用的。但是,现在我反身做:)
蒂姆在2009年

5

很少有重要的事情要注意的制作服务器变更前:

  • 确保我在正确的服务器上

  • 请注意“此操作将影响多少人*”(无论您是否犯错)

  • 在键入“ enter”键之前,请注意撤消操作可能性

  • 问问自己该命令是否有可能断开会话连接(fw规则,错误的关闭等)。确保您要进行故障转移(特别是如果您不在现场)


4

如果尚未完成,则将rm别名为rm -i


7
不不不不。这是您可以做的最坏的事情之一。有一天,您会发现自己在没有别名的盒子上,或者以某种方式破坏了我们的环境。学习使用rm -i代替。
olle

不不不不。做这个。有一天,您会不小心做错了事并保存自己。通常,您会忘记将-i放在行上并搞砸并删除错误的内容。
杰鲁布(Jerub)

如果我曾经在多台机器上工作,我就不会这么做。在设置新机器之前,要对其进行设置是一个巨大的挑战。
斯洛伐克,

可怕的是,@ olle和@Jerub都是正确的。在PS1上放置一些可能是彩色的标志以指示“安全关闭” /“安全开启”可能是明智的……
ikso 2011年

4

规则1-进行备份

规则2- 切勿在标准命令中添加“ molly Guard”包装器,确定自己的版本,但不要接管该名称,当您使用未设置的系统时,它只会咬你。

根目录和(部分)目录树的不同颜色等提示性技巧是很好的帮手,但同样,请确保没有它们就可以工作。


我以前从未听过这个词是什么“害羞守卫”?
詹森(Jason Tan)


4

这看起来似乎违反直觉并且不那么荒谬,但是我拥有的最佳命令行安全提示是:如果可以使用GUI模式替代方案并且切实可行,那么请使用它

为什么?非常简单。GUI模式通常具有一个内置的安全网,其形式为“警告-您将对freeblefrop咆哮,确定要这样做吗?” 即使没有,它也会减慢您的速度,给您更多的思考时间。它使您可以更轻松地在提交选项之前仔细检查选项,还可以在状态之前和之后进行屏幕截图,从而保护您免受错别字的影响;所有好的,有用的和有用的东西。

在可怕的“ rm -rf”经典情况下,您是否认为从GUI或CLI意外发布它更容易?

最终,诉诸GUI不会感到羞耻。它不会绝对防止重大灾难;在GUI中和在CLI中一样,尽可能使触发器满意;但是,一旦证明您值得,它就能为您省钱。


3

使用常识,不要运行您不了解的命令。那都是很好的建议。如果您想写出传递给rm的所有内容的绝对路径或通过sudo运行任何内容而感到痛苦,请放心。那我更喜欢su -c。至少它不缓存密码。我对让任何普通用户在无需密码验证的情况下以root特权运行代码感到不满意。

您可以在〜/ .bashrc中放一些东西,以使事情更安全一些,例如:

alias srm='rm -i'

让您有一个安全的rm替代品,...

但是最后,您可以并且永远会搞砸。前几天,我有一个失效的配置脚本,将我的整个/ usr / bin文件夹塞满了,打破了几件事。是的,任何有错误的软件的简单“ make install”安装都可能会破坏系统。无论您做什么,您永远都不安全。我要说的是,最重要的是:

保持定期备份。


2
再次-永远不要别名“ rm”。最终,当您在没有别名的系统上工作时,就会被它所困扰。
SilentW

一个非常糟糕的主意。如果您发现自己在Mac OS X(也许是其他平台?)上srm安全的,请删除
摩根,2012年

3

与其将rm别名为rm -i而不是别名,不如说删除或安全删除(并使用它们作为您的首选删除工具)更好。然后,当您使用尚未进行此设置的盒子时,不会造成任何损坏。


2

确保您永远不要运行在网上找到的命令,除非您完全了解它们在做什么。

您的系统可能与发布者的系统不同,这可能会造成伤害。


2

从Unix / Linux的角度来看,一个明显的命令行安全性是正确使用root帐户。
rm -rf作为root用户通常比作为用户更危险,并且使用sudo之类的内置功能而不是以root用户身份登录至关重要。一个简单的好朋友通常会帮助精神分裂症或多种人格。

该命令和前面的命令会响应任何文件更改命令,尤其是在您要确保您具有全局或正则表达式匹配权限的情况下。


2

在您正在处理的计算机上建立辅助连接可能会很方便,以防您杀死主要会话,或者做一些愚蠢的事情将其锁定,繁重的处理等。

这样,您仍然可以访问计算机,并且可以终止您的主要会话。

上面的大多数注释都涉及rm,但是我也用其他命令做了一些愚蠢的事情...

ifconfig可以关闭网络-哎呀,这需要物理状态才能修复。

至于脚本,我通常在两个窗口中工作。第一个用于编写脚本,第二个用于在编写脚本时测试每一行。慢慢地仔细工作,我可以确保编写代码时每一行都能按预期工作,并注意保持相同的变量等。

就个人而言,我找不到像rm -i这样的东西的额外提示。在诉苦,压力重重等情况下,我会犯大部分错误,而这些时候我只是大声疾呼而无视提示。坏习惯也许。


2

如果您使用bash,请尝试以下操作:

TMOUT=600

在您/root/.bashrc或类似的人中。它会在10分钟后自动将您注销,从而减少了您偶然翻到根终端并键入一些愚蠢的根终端的机会。

是的,我知道您应该使用sudo执行root命令-这只是一个额外的安全网,以防万一您决定冒险使用它。


2
# Allow only UPDATE and DELETE statements that specify key values
alias mysql="mysql --safe-updates"`

如果您曾经使用mysql CLI,强烈建议使用别名。


1

我使用lcho而不是ls,以便在shell扩展所有内容后可以看到完整的命令。另外,请始终对表示文件的双引号变量使用双引号,以便您的东西可以使用可能带有制表符或空格的文件名。


1

*尽可能避免将glob作为其自变量。即使我确实的意思是“删除此目录中的所有内容”,我也会尝试更具体一些。rm *.php。万一我意外地在另一个目录中运行了相同的命令,这是一种先发制人的损害控制。


我学会了从不“ cd dir; rm -rf *”,而是始终“ rm -rf dir”,尽可能具体。
斯洛伐克,

1

让您思考自己正在做的事情的一种好方法是在root的bashrc中添加以下内容(cshrc,随便什么):

unset PATH

这样,您必须执行/ bin / rm而不是仅仅执行“ rm”。这些多余的字符可能会让您思考。


好的,我要在哪里运行此命令?which $COMMAND不再有效。
凯文M

/ usr / bin / locate $ COMMAND吗?
比尔·魏斯

更好的是,/ usr / bin / locate -r / $ COMMAND $
Bill Weiss,

1

对于复杂的正则表达式,尤其是“查找”命令将回声放在最前面,并将其捕获到文件中。然后,您可以在使用“源代码”执行文件之前,检查您是否确实确实删除/移动了/等了您认为的内容。

手动添加正则表达式未拾取的那些边缘情况也很方便。


1

一些其他文章的一些要点:我使用首先建议的常规echo / ls步骤,以确保命令选择了我想要的文件集,或者由shell解释为预期的文件集。

但是随后,我使用外壳程序的命令历史记录编辑功能来检索上一个命令,并仅修改需要更改的部分。

单独键入这些命令根本没有帮助...

$ ls *.bak
$ echo rm *.bak
$ rm * .bak

...因为我不小心在最后一行输入了空格,并删除了所有文件。我将始终检索上一行,并简单地删除“ echo”。


1

root用户:
除非必须,否则不要成为root用户。
如果供应商说需要以root用户身份运行,请告诉他们您是客户,并且您要以非root用户身份运行它。
有多少现成的软件包希望“仅仅因为它更容易”而成为根?

习惯:
永远不要在没有看过三遍的情况下将'*'与remove一起使用。最好养成先使用ls -l TargetPattern的习惯,然后再使用'rm!$'。最大的威胁不是您所想。我几乎和“ ls”一样经常键入“ hostname”!

拐杖:
标准提示和“ alias rm ='rm -i'”之类的别名很有帮助,但是我经常无法完全控制自己所在的计算机,因此我只使用Expect包装程序脚本来设置路径,提示和带有“ -i”的别名

查找问题:
使用完整路径会有所帮助,但是在不可能的情况下,将cd放入更安全的位置,也请使用'&&'来确保'cd'成功执行,然后再查找,删除,tar,untar,等等:
例如:cd /filesystema && tar cf - | ( cd /filesystemb && tar vxf -)
在这种情况下,使用“ &&”可以防止将tar文件提取到自身之上(尽管在这种情况下,“ rsync”会更好)

removes:
如果可以帮助,则不要递归地删除,尤其是在脚本中。使用-type f和-name'pattern'查找并删除,我仍然担心不给xargs提供任何信息... tar和untar来回移动(改用rsync)


1

如果使用操作系统的多个变体,请非常注意语法上的差异。在一个unix变体上合理地安全的事物在另一个变体中极其危险。

示例:killall

Linux / FreeBSD / OSX-杀死所有与传递的参数匹配的进程。例如:“ killall apache”杀死所有apache,而其他所有进程都保留下来。

Solaris-杀死所有进程。不完全是。在手册页中:shutdown(1M)使用killall杀死所有与关闭过程没有直接关系的活动进程。


我在前雇主的备份服务器上了解到这一点。当它运行时,晚上的录像带。哎呀
比尔·魏斯

1
您可以使用pkill来代替,它可以在solaris和linux上使用。
詹森(Jason Tan)

0

代替

rm foo*

使用

rm -i foo*

这对于少数文件是可行的,但对于整个tarball而言却并非如此。这就是为什么混叠rm会妨碍您的原因。


这就是-f开关的作用:覆盖任何先前的-i开关。如果将其放入.bash_profile或类似的shell初始化脚本中,则无需担心。只要确保您要这样做,就已经有人说过了,而且更雄辩。
凯文M

0

首先使用echo运行命令是个好主意,但仍然容易出现错别字。

尝试将其与!$等扩展名一起使用。

echo foo*
rm -rf !$

!$扩展为最后一个命令的最后一个单词,因此等效于

echo foo*
rm -rf foo*

还有!*,它扩展为最后一个命令的所有参数。

确实,如果您愿意的话,可以这样做

echo rm -rf foo*
!*

(如果使用的是ksh而不是bash,则可以键入Esc +句号来插入最后一个单词。)


Esc +。也可以使用bash。
olle

0

在某些情况下:

ls * .php
echo rm * .php
rm * .php

您可以使用替换运算符,如下所示:
$ ls * .php
<dir listing>

$ ^ ls ^ echo rm(此命令将前一个命令中的ls替换为echo rm,其余命令行保持不变)

$ ^ echo rm ^ rm(将echo rm替换为rm,因此您不必重新输入* .php并在错误的时间插入空格)

^ = shift-6,对于不熟悉它的人。


ck 我宁愿使用箭头键并编辑上一行。这样,当我按Enter键时,我可以看到将要运行什么命令,而不必盲目地相信自己正确的替换模式。
Marius Gedminas

例如,在“ echo rm * .php”之后,您先执行<Up> <Home> <Alt-D>,然后再执行<Enter>。
Marius Gedminas

0

使用bash并设置PS1 ='\ u @ \ h:\ w>'。如其他答案中所述,这将扩展为username @ hostname:/ full / working / directory / path>,如果无法更新.profile或.bash_profile文件,则可以在每次登录时使用Expect设置环境。改变背景颜色很容易是最好的答案:-)


-1

是的。通过IRC通过一个名为“ -rf”的文件向某人发送文件的古老技巧,使其最终在他们的〜目录中。后来,一个小小的“ rm -rf”(而不是“ rm--rf”)和许多笑声随之而来,因为他们吸取了关于不以root身份运行IRC的严厉教训。


rofl因子+1
David Z

那么“ rm -rf”应该如何伤害您呢?
2009年

也许文件实际上被命名为“ -rf *”?
Marius Gedminas

-1

而不是像这样使用rm -rf <dir>放在-rf末尾:rm <dir> -rf。认为这是在瞄准后和开火之前消除了安全。这样,如果您在输入目录名称(或使用制表符补全)时滑回车键并具有类似名称的目录,则可以保护您。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.