使用shell脚本将一行追加到/etc/hosts文件中

75

我有一个新的Ubuntu 12.04 VPS。我正在尝试编写一个安装脚本,完成整个LAMP安装。我遇到困难的是在/etc/hosts文件中添加一行。我的当前hosts文件如下:

127.0.0.1       localhost Venus

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

我希望它看起来像这样:

127.0.0.1       localhost Venus
192.241.xx.xx  venus.example.com venus

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

我已经尝试了各种使用追加命令 (\a) 的 sed 命令。由于某种原因,Ubuntu 要么只在终端中回显 hosts 文件的内容,要么根本不做任何事情。我该如何使用 Bash 脚本正确地将第二行注入到文件中?


1
如果您被允许安装软件包,那么https://github.com/alphabetum/hosts看起来是一个不错的解决方案。 - revau.lt
7个回答

69

请确保使用sed命令的-i选项。

-i[SUFFIX], --in-place[=SUFFIX]
  edit files in place (makes backup if extension supplied)

sed -i "2i192.241.xx.xx  venus.example.com venus" /etc/hosts
否则,
echo "192.241.xx.xx  venus.example.com venus" >> /etc/hosts

将该行追加到文件末尾,这可以按照您的期望工作。


1
这假设 127.0.0.1 行是输入流的第一行(插入应该在第二行完成)。在许多情况下,这可能是正确的,但值得一提。 - kojiro
5
-bash: /etc/hosts: 权限不足。有什么想法? - Alex2php
1
@Alex2php 请确保您拥有根访问权限以修改该文件。 - damienfrancois
17
这个命令对我解决了问题: sudo -- sh -c "echo test >> /etc/hosts"如果我想要追加一些内容,仅使用 sudo 命令是行不通的... - Alex2php
3
请注意,在 Mac 上,您需要指定 -i '',例如 sed -i '' '2i192.241.11.22 venus.example.com venus' /etc/hosts。即使为空,Mac 版本的 sed 也需要 -i 的扩展参数。 - Doktor J
显示剩余3条评论

50

如果您使用的是Mac或需要sudo权限,请尝试以下操作:

sudo -- sh -c -e "echo '192.34.0.03   subdomain.domain.com' >> /etc/hosts";

它仍会要求您输入密码。

@kainjow 提供了另一种方法。

echo '192.34.0.03 subdomain.domain.com' | sudo tee -a /etc/hosts

8
您也可以使用tee命令:echo '192.34.0.03 subdomain.domain.com' | sudo tee -a /etc/hosts - kainjow
1
这似乎也适用于Ubuntu 16。 - Francisco Luz
完美,正是我想要的。不过,我很想知道 -- sh -c -e 到底是做什么的?我更喜欢知道我在终端中输入的内容,而不只是复制粘贴 :) - powerbuoy
你不需要使用“-e” - spex
2
@powerbuoy 双破折号“--”用于shell命令中表示命令选项的结束,此后只接受位置参数。sh是与标志-c一起使用的shell命令解释器,它使命令从字符串操作数而不是标准输入读取。对于我们的用例来说,-e标志是不必要的,但在非交互模式下,如果任何未经测试的命令失败,则会导致解释的命令立即退出。 - spex
警告:这将完全覆盖您的“hosts”文件。在继续使用“tee”之前,请确保备份您的“hosts”文件。备份文件的命令为“sudo cp /etc/hosts /etc/hosts.bak”。 - Artem Kozlenkov

38

插入/更新条目

如果你想使用bash编程方式插入/更新主机条目,这里是我写的一个脚本:

#!/bin/bash

# insert/update hosts entry
ip_address="192.168.x.x"
host_name="my.hostname.example.com"
# find existing instances in the host file and save the line numbers
matches_in_hosts="$(grep -n $host_name /etc/hosts | cut -f1 -d:)"
host_entry="${ip_address} ${host_name}"

echo "Please enter your password if requested."

if [ ! -z "$matches_in_hosts" ]
then
    echo "Updating existing hosts entry."
    # iterate over the line numbers on which matches were found
    while read -r line_number; do
        # replace the text of each line with the desired host entry
        sudo sed -i '' "${line_number}s/.*/${host_entry} /" /etc/hosts
    done <<< "$matches_in_hosts"
else
    echo "Adding new hosts entry."
    echo "$host_entry" | sudo tee -a /etc/hosts > /dev/null
fi

该脚本旨在用于OS X,但也可以在linux上进行轻微调整后使用。


脚本太复杂,只添加一行不切实际。 - José Ibañez
4
在我看来,这是一个比仅仅在etc/hosts文件中添加一行更好的解决方案。 - CodeUK
这很完美,但是更新部分的效果并不如预期。即使IP地址和主机名组合已经存在,它仍然会继续添加行。我还进行了一些小的调整,以便脚本将使用IP地址和主机名作为参数,而不是硬编码。 - Kalpesh Popat
太好了,谢谢!只是稍微更改了grep正则表达式为grep -n "^[^#]*${host_name}" /etc/hosts,以便在注释行中也忽略可能的匹配。 - tomorrow

5
echo "127.0.0.1 localhost `hostname`">./temp_hosts
echo "192.241.xx.xx  venus.example.com">>./temp_hosts
cat /etc/hosts |tail -n +2 >>./temp_hosts
cat ./temp_hosts > /etc/hosts
rm ./temp_file

谢谢您的回复,弗拉基米尔。我也会测试您的方法,并在此发布结果,以便于未来访问者受益。 - Stephen Howells
@Ingo,你真的认为建议某人不要尝试某事(假设该事情并不危险)是合适的吗?让这个人去实验吧! - kojiro

2
我应该指出,流编辑器sed并不是用来编辑文件的,虽然它可以用来做到这一点。 (标准sed没有内置机制来写入除标准输出之外的内容。) 更合适的工具是ed
下面的ed脚本表示“查找包含(虽然有点随意)正则表达式/127.0.0.1/的行,并在下一行附加”。(孤立的句号告诉ed停止添加。)
ed /etc/hosts <<-'EOF'
    /127.0.0.1/a
    192.241.xx.xx  venus.example.com
    .
    wq
EOF

话虽如此,你可以非常简单地将此行追加到您的/etc/hosts文件的末尾

echo '192.241.xx.xx  venus.example.com' >> /etc/hosts

1
我以前从未使用过 ed。它似乎非常强大,会很有用。谢谢你的分享。 - Stephen Howells
对于某些用户,根据其权限设置,您可能需要使用sudo -- sh -c "echo '192.241.xx.xx venus.example.com' >> /etc/hosts"而不是简单地使用sudo echo ...,否则会出现“权限被拒绝”的错误。 - spex

1
您可以使用sed,例如:

sed '/Venus/ a\  
192.241.xx.xx  venus.example.com venus' /etc/hosts

-2

尝试使用root访问权限。

 public void edithost() {
    sudo("echo " + "192.168.43.1     www.openrap.com openrap" + " >> /etc/hosts");
    sudo("echo " + "192.168.43.1  openrap.com openrap" + " >> /etc/hosts");
    sudo("echo " + "192.168.2.144  www.openrap.com openrap" + " >> /etc/hosts");
    sudo("echo " + "192.168.2.144  openrap.com openrap" + " >> /etc/hosts");
}

sudo 用于获取超级用户权限

public static void sudo(String... strings) {
    try {
        Process su = Runtime.getRuntime().exec("su");
        DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());

        for (String s : strings) {
            outputStream.writeBytes(s + "\n");
            outputStream.flush();
        }

        outputStream.writeBytes("exit\n");
        outputStream.flush();
        try {
            su.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

这将把这些行附加到 Android 中的 hosts 文件中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接