Go library and CLI utility for /etc/hosts management.

txeh - /etc/hosts mangement

Etc Hosts Management Utility & Go Library

Go Report Card GoDoc

/etc/hosts Management

It is easy to open your /etc/hosts file in text editor and add or remove entries. However, if you make heavy use of /etc/hosts for software development or DevOps purposes, it can sometimes be difficult to automate and validate large numbers of host entries.

txeh was initially built as a golang library to support kubefwd, a Kubernetes port-forwarding utility utilizing /etc/hosts heavily, to associate custom hostnames with multiple local loopback IP addresses and remove these entries when it terminates.

A computer's /etc/hosts file is a powerful utility for developers and system administrators to create localized, custom DNS entries. This small go library and utility were developed to encapsulate the complexity of working with /etc/hosts directly by providing a simple interface for adding and removing entries in a /etc/hosts file.

txeh Utility

Install

MacOS homebrew users can brew install txn2/tap/txeh, otherwise see releases for packages and binaries for a number of distros and architectures including Windows, Linux and Arm based systems.

Complie and run from source (dependencies are vendored):

go run ./util/txeh.go

Use

The txeh CLI application allows command line or scripted access to /etc/hosts file modification.

Example CLI Usage:

 _            _
| |___  _____| |__
| __\ \/ / _ \ '_ \
| |_ >  <  __/ | | |
 \__/_/\_\___|_| |_| v1.1.0

Add, remove and re-associate hostname entries in your /etc/hosts file.
Read more including useage as a Go library at https://github.com/txn2/txeh

Usage:
  txeh [flags]
  txeh [command]

Available Commands:
  add         Add hostnames to /etc/hosts
  help        Help about any command
  remove      Remove a hostname or ip address
  version     Print the version number of txeh

Flags:
  -d, --dryrun         dry run, output to stdout (ignores quiet)
  -h, --help           help for txeh
  -q, --quiet          no output
  -r, --read string    (override) Path to read /etc/hosts file.
  -w, --write string   (override) Path to write /etc/hosts file.
hosts.test # specify an alternate /etc/hosts file to read. writing will # default to the specified read path. txeh add 127.1.27.100 dev2.example.com -q -r ./hosts.test # specify a seperate read and write oath txeh add 127.1.27.100 dev3.example.com -r ./hosts.test -w ./hosts.test2 ">
# point the hostnames "test" and "test.two" to the local loopback
sudo txeh add 127.0.0.1 test test.two

# remove the hostname "test"
sudo txeh remove host test

# remove multiple hostnames 
sudo txeh remove host test test2 test.two

# remove an IP address and all the hosts that point to it
sudo txeh remove ip 93.184.216.34

# remove multiple IP addresses
sudo txeh remove ip 93.184.216.34 127.1.27.1

# remove CIDR ranges
sudo txeh remove cidr 93.184.216.0/24 127.1.27.0/28

# quiet mode will suppress output
sudo txeh remove ip 93.184.216.34 -q

# dry run will print a rendered /etc/hosts with your changes without
# saving it.
sudo txeh remove ip 93.184.216.34 -d

# use quiet mode and dry-run to direct the rendered /etc/hosts file
# to another file
sudo txeh add 127.1.27.100 dev.example.com -q -d > hosts.test

# specify an alternate /etc/hosts file to read. writing will
# default to the specified read path.
txeh add 127.1.27.100 dev2.example.com -q -r ./hosts.test

# specify a seperate read and write oath
txeh add 127.1.27.100 dev3.example.com -r ./hosts.test -w ./hosts.test2

txeh Go Library

Dependency:

go get github.com/txn2/txeh

Example Golang Implementation:

package main

import (
    "fmt"
    "strings"

    "github.com/txn2/txeh"
)

func main() {
    hosts, err := txeh.NewHostsDefault()
    if err != nil {
        panic(err)
    }

    hosts.AddHost("127.100.100.100", "test")
    hosts.AddHost("127.100.100.101", "logstash")
    hosts.AddHosts("127.100.100.102", []string{"a", "b", "c"})
    
    hosts.RemoveHosts([]string{"example", "example.machine", "example.machine.example.com"})
    hosts.RemoveHosts(strings.Fields("example2 example.machine2 example.machine.example.com2"))

    
    hosts.RemoveAddress("127.1.27.1")
    
    removeList := []string{
        "127.1.27.15",
        "127.1.27.14",
        "127.1.27.13",
    }
    
    hosts.RemoveAddresses(removeList)
    
    hfData := hosts.RenderHostsFile()

    // if you like to see what the outcome will
    // look like
    fmt.Println(hfData)
    
    hosts.Save()
    // or hosts.SaveAs("./test.hosts")
}

Build Release

Build test release:

goreleaser --skip-publish --rm-dist --skip-validate

Build and release:

GITHUB_TOKEN=$GITHUB_TOKEN goreleaser --rm-dist

License

Apache License 2.0

Owner
txn2: Kubernetes apps and system utilities.
Parts for Kubernetes based platforms, development operations, proxies and data pipelines.
txn2: Kubernetes apps and system utilities.
Comments
  • open /etc/hosts: permission denied

    open /etc/hosts: permission denied

    I am using this as Go library and when I try to just run the example provided in the README file, the final 'hosts.Save()' throws 'open /etc/hosts: permission denied' error. Can you add details to provide root access?

  • Added empty path checking func and adjusted some of the root.go code

    Added empty path checking func and adjusted some of the root.go code

    Added some export comments to the exported vars, removed some extra blank lines, and made small changes to the initEtcHosts func.

    Also added go modules to remove the GOPATH dependency.

  • Add command line option to show /etc/hosts content

    Add command line option to show /etc/hosts content

    I use txeh as command line tool to manage the hosts file, though I need to cat the file to see its content. Having a built-in option would be very handy :)

  • multiple host occurences are ignored

    multiple host occurences are ignored

    When there are multiple hosts with the same name in a hosts file only the first one will be updated on addHosts. See https://github.com/txn2/txeh/blob/master/txeh.go#L261

    You can test this with the following hosts file

    127.0.0.1 abc 128.0.0.1 abc 129.0.0.1 abc

    now try to add 130.0.0.1.

  • fixes #10 handle no newline issue

    fixes #10 handle no newline issue

    test

    func TestHost(t *testing.T) {
    	hostsfile := "/tmp/hosts.txt"
    
    	data := []byte("127.0.0.1 localhost")
    	err := ioutil.WriteFile(hostsfile, data, 0644)
    	if err != nil {
    		t.Error("prepare test hosts file err", err)
    		return
    	}
    
    	hosts, err = txeh.NewHosts(&txeh.HostsConfig{
    		ReadFilePath:  hostsfile,
    		WriteFilePath: hostsfile,
    	})
    	if err != nil {
    		t.Error("create hosts err", err)
    		return
    	}
    	spew.Dump("hosts: ", hosts)
    	t.Logf("init: %q\n", hosts.RenderHostsFile())
    }
    

    origin

    === RUN   TestHost
    (string) (len=7) "hosts: "
    (*txeh.Hosts)(0xc00009a4e0)({
     Mutex: (sync.Mutex) {
      state: (int32) 0,
      sema: (uint32) 0
     },
     HostsConfig: (*txeh.HostsConfig)(0xc0000ba180)({
      ReadFilePath: (string) (len=14) "/tmp/hosts.txt",
      WriteFilePath: (string) (len=14) "/tmp/hosts.txt"
     }),
     hostFileLines: (txeh.HostFileLines) {
     }
    })
        TestHost: hosts_test.go:37: init: ""
        TestHost: hosts_test.go:50: after add:  1.1.1.1          demo.com
            
        TestHost: hosts_test.go:61: after remove: 
    

    after fixes

    === RUN   TestHost
    (string) (len=7) "hosts: "
    (*txeh.Hosts)(0xc00010c480)({
     Mutex: (sync.Mutex) {
      state: (int32) 0,
      sema: (uint32) 0
     },
     HostsConfig: (*txeh.HostsConfig)(0xc000122180)({
      ReadFilePath: (string) (len=14) "/tmp/hosts.txt",
      WriteFilePath: (string) (len=14) "/tmp/hosts.txt"
     }),
     hostFileLines: (txeh.HostFileLines) (len=1 cap=1) {
      (txeh.HostFileLine) {
       OriginalLineNum: (int) 0,
       LineType: (int) 30,
       Address: (string) (len=9) "127.0.0.1",
       Parts: ([]string) (len=2 cap=2) {
        (string) (len=9) "127.0.0.1",
        (string) (len=9) "localhost"
       },
       Hostnames: ([]string) (len=1 cap=1) {
        (string) (len=9) "localhost"
       },
       Raw: (string) (len=19) "127.0.0.1 localhost",
       Trimed: (string) (len=19) "127.0.0.1 localhost",
       Comment: (string) ""
      }
     }
    })
        TestHost: hosts_test.go:37: init: "127.0.0.1        localhost\n"
        TestHost: hosts_test.go:50: after add:  127.0.0.1        localhost
            1.1.1.1          demo.com
            
        TestHost: hosts_test.go:61: after remove:  127.0.0.1        localhost
    
  • Adding hosts lowercases the hostname

    Adding hosts lowercases the hostname

    Update: maybe this isn't the issue after all. I was able to get things to work by skipping TLS verification and it was with both upper and lower case host names.

  • Handle trailing comments on a hosts file line.

    Handle trailing comments on a hosts file line.

    What this PR does / why we need it:

    The current ParseHosts implementation does not take into consideration trailing comments in an /etc/hosts entry. For such an entry, the AddHosts API fails, as it adds an entry as a comment. For ex. For the following /etc/hosts file

    # comment 1
    # comment 2
    
    127.0.0.1 localhost # some comment
    

    AddHosts("127.0.0.1", "localhost-1") will update the /etc/hosts file incorrectly like this

    # comment 1
    # comment 2
    
    127.0.0.1 localhost # some comment localhost-1
    

    This PR addresses the above problem.

  • supoort hosts with duplicate ip for one fqdn

    supoort hosts with duplicate ip for one fqdn

    I know you have removed duplicate address for same fqdn, but if the hosts file is used by dnsmasq, it will need that to implement round robin dns address load balance. so maybe it's a good idea to keep these lines if a parameter is specified.

  • Comment/Uncomment routines

    Comment/Uncomment routines

    It would be useful for the library to have Comment() and Uncomment() routines to change the LineType of a HostFileLine without actually remove the ip-fqdn reference

  • Multiple blank lines at the end of the file

    Multiple blank lines at the end of the file

    I noticed that if I made 2+ consecutive Save() calls, the file ends up with a bunch of blank lines at the end. I think this can be a point to look at https://github.com/txn2/txeh/blob/09e29537ecce61eafea9f21a18fd2f5e272074a6/txeh.go#L278 The use of Sprintln adds a "\n" at the end of every line, which can be ok except for the last line.

  • Show hosts by ip

    Show hosts by ip

    It would be useful to also show the hosts by an IP, or vice-versa. Would you be open to this feature and pull request?

    Something along the lines of this:

    hosts.ListHosts(ip) // returns []string{}
    hosts.ListIP(hosts) // returns string
    
Stack Up is a simple deployment tool that performs given set of commands on multiple hosts in parallel.
Stack Up is a simple deployment tool that performs given set of commands on multiple hosts in parallel.

Stack Up is a simple deployment tool that performs given set of commands on multiple hosts in parallel. It reads Supfile, a YAML configuration file, which defines networks (groups of hosts), commands and targets.

Jan 1, 2023
Hostover is a hosts file poisoning script written in Go
Hostover is a hosts file poisoning script written in Go

Hostover - Hosts file Poisoner Hostover is a hosts file poisoning script written in Go It will poison the hosts file with fake IP-Domain connections,

Jan 1, 2022
Easy to use library and CLI utility to generate Go struct from CSV files.

csv2struct Easy to use library and CLI utility to generate Go struct from CSV files. As a benefit, it's fully compatible with csvutil. So, structs gen

Nov 7, 2022
A CLI tool for get meta infomation, for SEO, Testing , etc

What is meta-curl ? meta-curl is a CLI tool for get meta infomation, for SEO, Testing , etc. This can be used like curl CLI command. How to Use(wip) G

Nov 16, 2021
tfacon is a CLI tool for connecting Test Management Platforms and Test Failure Analysis Classifier.

Test Failure Classifier Connector Description tfacon is a CLI tool for connecting Test Management Platforms and Test Failure Analysis Classifier. Test

Jun 23, 2022
a work time management CLI tool for any platform
a work time management CLI tool for any platform

english |日本語 jobgosh | job management tool made with golang for shell a multi-platform work time management CLI tool to track and improve your day to

May 16, 2022
Google KMS backed Solana key management CLI tool

solana-kms solana-kms is a Google KMS backed Solana token management CLI utility. The main purpose of the tool is to ensure that the private key is ne

Jan 13, 2022
High level CLI utility for restic
High level CLI utility for restic

High level CLI utility for restic

Dec 26, 2022
Utility CLI to convert Spring Boot Yaml configuration into external configuration

boot-config-export Utility CLI to convert Spring Boot Yaml configuration into external configuration (as environment variables). The variables are tra

Nov 17, 2021
A dead simple cli utility to help you manage your git stash
A dead simple cli utility to help you manage your git stash

A dead simple cli utility to help you manage your git stash.

Aug 2, 2022
Related is a simple cli utility tool to create files or a group of files.

Related - Create files based on individual definitions or groups Related helps with common file-creation-based tasks. You can predefine single types a

Apr 16, 2022
Syno-cli - Synology unofficial API CLI and library

Synology CLI Unofficial wrapper over Synology API in Go. Focus on administrative

Jan 6, 2023
A command line utility and library for generating professional looking invoices in Go.
A command line utility and library for generating professional looking invoices in Go.

ginvoicer A command line utility and library for generating professional looking invoices in Go. This is a very rough draft and there could still be b

Dec 15, 2022
👀 A modern watch command. Time machine and pager etc.
👀 A modern watch command. Time machine and pager etc.

Viddy Modern watch command. Viddy well, gopher. Viddy well. Demo Features Basic features of original watch command. Execute command periodically, and

Jan 2, 2023
Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc.

bntp.go Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc. Neovim int

Sep 13, 2022
CLI to run a docker image with R. CLI built using cobra library in go.
CLI  to run a docker image with R. CLI built using cobra library in go.

BlueBeak Installation Guide Task 1: Building the CLI The directory structure looks like Fastest process: 1)cd into bbtools 2)cd into bbtools/bin 3)I h

Dec 20, 2021
Reusable golang-migrate library using cobra utility

shift Reusable golang-migrate library using cobra utility Example Usage package main import ( "sql/db" "github.com/purwandi/shift" "github.com

Dec 16, 2021
Utilities to prettify console output of tables, lists, progress-bars, text, etc.
Utilities to prettify console output of tables, lists, progress-bars, text, etc.

go-pretty Utilities to prettify console output of tables, lists, progress-bars, text, etc. Table Pretty-print tables into ASCII/Unicode strings.

Dec 29, 2022
OTF font with vertical bars for one-line ASCII spectrum analyzers, graphs, etc
OTF font with vertical bars for one-line ASCII spectrum analyzers, graphs, etc

graph-bars-font OTF font with vertical bars for one-line ASCII spectrum analyzers, graphs, etc. I didn't find anything similar on the net so I decided

Jul 28, 2022