使用 scp 免密码传输
在本文中,我将向您展示如何在不使用密码的情况下使用 scp(安全复制)命令。然后,我将向您展示如何在两个脚本中使用此命令。一个脚本允许您将文件复制到网络上的多台 Linux 机器,另一个脚本允许您轻松备份所有 Linux 机器。
如果您是 Linux 系统管理员,您经常需要将文件从一台 Linux 机器复制到另一台。或者,您可能需要将文件分发到多台机器。您可以使用 FTP,但使用 scp 有许多优点。例如,scp 比 FTP 安全得多。 scp 在 LAN/WAN 上以加密方式传输,而 FTP 使用明文,甚至包括密码。
但我最喜欢 scp 的地方是它很容易编写脚本。假设您需要将文件分发到 100 台 Linux 机器。我宁愿编写一个脚本来完成这项工作,也不愿键入 100 组复制命令。如果您在脚本中使用 FTP,事情可能会变得混乱,因为您登录的每台 Linux 机器都会要求输入密码。但是,如果您在脚本中使用 scp,您可以进行设置,使远程 Linux 机器不要求输入密码。信不信由你,这实际上比使用 FTP 安全得多。
这是一个演示 scp 最基本语法的示例。要将名为 abc.tgz 的文件从本地 PC 复制到名为 bozo 的远程 PC 的 /tmp 目录,请使用
scp abc.tgz root@bozo:/tmp
现在系统会要求您输入 bozo 的 root 密码,所以我们还没有完全实现目标。系统仍然要求输入密码,因此不易编写脚本。要解决此问题,请按照以下一次性步骤操作,之后您可以进行无数次免密码 scp 复制
确定本地机器上哪个用户稍后将使用 scp。当然,root 用户拥有最大的权力,我个人就是这样做的。我不会在这里给您讲关于 root 用户危险的课,所以如果您不了解这些危险,请选择其他用户。无论您选择哪个用户,现在都以该用户身份登录,并在接下来的步骤中保持登录状态。稍后使用 scp 时,也以同一用户身份登录。
在本地机器上生成公钥/私钥对。什么?如果您不熟悉公钥密码学,这里有一个 15 秒的解释。在公钥密码学中,您生成一对数学上相关的密钥,一个公钥和一个私钥。然后,您将您的公钥提供给世界上任何人,但您永远不要泄露您的私钥。神奇之处在于密钥的数学构成;任何拥有您的公钥的人都可以使用它来加密消息,但只有您可以使用您的私钥来解密它。无论如何,创建密钥对的语法是
ssh-keygen -t rsa
在响应中,您应该看到
Generating public/private rsa key pair Enter file in which to save the key ...
按 Enter 键接受此操作。
在响应中,您应该看到
Enter passphrase (empty for no passphrase):
您不需要密码短语,因此按两次 Enter 键。
在响应中,您应该看到
Your identification has been saved in ... Your public key has been saved in ...
记下刚刚生成的公钥的名称和位置。它总是以 .pub 结尾。
将刚刚生成的公钥复制到您的所有远程 Linux 机器。您可以使用 scp 或 FTP 或任何其他方式进行复制。假设您使用的是 root 用户——再次强调,请参阅步骤 1 中的警告——密钥必须包含在文件 /root/.ssh/authorized_keys 中。或者,如果您以用户身份登录,例如 clyde,它将位于 /home/clyde/authorized_keys 中。请注意,authorized_keys 文件可以包含来自其他 PC 的密钥。因此,如果该文件已存在并且包含文本,则需要将您的公钥文件的内容附加到已有的内容中。
现在,如果运气好的话,您应该能够在不使用密码的情况下将文件 scp 到远程机器。因此,让我们通过再次尝试我们的第一个示例来测试它。将名为 xyz.tgz 的文件从您的本地 PC 复制到名为 bozo 的远程 PC 的 /tmp 目录
scp xyz.tgz root@bozo:/tmp
哇——复制成功,无需密码!
在继续之前,先说一下安全性。这台本地 PC 变得非常强大,因为它现在只需一个本地密码即可访问所有远程 PC。因此,这个密码最好是强密码且受到良好保护。
现在进入有趣的部分。让我们编写一个简短的脚本,将名为 houdini 的文件从本地 PC 复制到十台远程 PC 的 /tmp 目录,这十台 PC 位于十个不同的城市,只需五分钟的工作时间。当然,它同样适用于 100 台或 1000 台 PC。假设这 10 台 PC 分别名为 brooklyn、oshkosh、paris、bejing、winslow、rio、gnome、miami、minsk 和 tokyo。这是脚本
#!/bin/sh for CITY in brooklyn oshkosh paris bejing winslow rio gnome miami minsk tokyo do scp houdini root@$CITY:/tmp echo $CITY " is copied" done
它像魔法一样工作。通过此脚本中的 echo 行,您应该能够看到每个城市的副本按顺序完成。
顺便说一句,如果您是 shell 脚本新手,这里有一个相当不错的教程。
您可能知道,scp 只是更广泛的 SSH 程序的一部分。这里是精彩的部分:当您按照我上面的六步过程操作后,您还可以坐在本地 PC 前,在任何远程 PC 上执行您喜欢的任何命令——当然,无需密码。这是一个简单的示例,用于查看远程 PC brooklyn 上的日期和时间
ssh brooklyn "date"
现在让我们将这两个概念结合起来,编写最后一个非常酷的脚本。这是一种粗略但有效的方式来备份所有远程 Linux 机器。该示例备份每台机器上的 /home 目录。与商业备份软件的功能相比,它很原始,但价格无与伦比。考虑一下大多数商业备份软件对您备份的每台机器收取许可费的事实。如果您使用这样的软件包,与其支付许可费来远程备份 100 台 PC,不如使用该脚本将 100 台 PC 备份到一台本地 PC。然后,将本地 PC 备份到您的商业软件包,并节省 99 台 PC 的许可费。无论如何,下面的脚本演示了这些概念,因此您可以编写自己的脚本来适应您自己的情况。只需将此脚本放在本地 PC 上的 cron 作业中;远程 PC 上不需要脚本。请仔细阅读注释,因为它们解释了您需要知道的一切
#!/bin/sh # Variables are upper case for clarity # before using the script you need to create a dir called '/tmp/backups' on each # remote box & a dir called '/usr/backups' on the local box # on this local PC # Set the variable "DATE" & format the date cmd output to look pretty # DATE=$(date +%b%d) # this 'for loop' has 3 separate functions for CITY in brooklyn oshkosh paris bejing winslow rio gnome miami minsk tokyo do # remove tarball on remote box from the previous time the script ran # to avoid filling up your HD # then echo it for troubleshooting # ssh -1 $CITY "rm -f /tmp/backups/*.tgz" echo $CITY " old tarball removed" # create a tarball of the /home dir on each remote box & put it in /tmp/backups # name the tarball uniquely with the date & city name # ssh $CITY "tar -zcvpf /tmp/backups/$CITY.$DATE.tgz /home/" echo $CITY " is tarred" # copy the tarball just create from the remote box to the /usr/backups dir on # the local box # scp root@$CITY:/tmp/backups/$CITY.$DATE.tgz /usr/backups echo $CITY " is copied" done # the rest of the script is for error checking only, so it's optional: # on this local PC # create error file w todays date. # If any box doesn't get backed, it gets written to this file # touch /u01/backup/scp_error_$DATE for CITY in brooklyn oshkosh paris bejing winslow rio gnome miami minsk tokyo do # Check if tarball was copied to local box. If not write to error file # note the use of '||' which says do what's after it if what's before it is not # true # ls /u01/backup/$CITY.$DATE.tgz || echo " $CITY did not copy" >> scp_error_$DATE # Check if tarball can be opened w/o errors. If errors write to error file. tar ztvf /u01/backup/$CITY.$DATE.tgz || echo "tarball of $CITY is No Good" >> scp_error_$DATE done
差不多就是这样了。在本文中,我试图给出一些示例来演示这些概念,这些示例不一定可以直接“按原样”使用。某些语法可能不适用于所有发行版,但为了简洁起见,我无法包含所有可能性。例如,如果您使用的是 Red Hat 6.2 或更早版本,则语法需要进行一些更改。因此,请发挥创造力,希望您可以在自己的环境中使用其中的一些工作。
版权所有 (c) 2004, Dave Sirof。最初发表于 Linux Gazette 第 98 期。版权所有 (c) 2004, Specialized Systems Consultants, Inc.