0

I am trying to manage a host file with a python script. I am new to python and I am having a hard time with figuring out how to replace a line if I find a match. For example, if the address gets changed in a host file for a website I want the script to find it and change it back. Thanks for your help.

import os
import time

#location to the host file to read and write to
hosts_path=r"C:\Windows\System32\drivers\etc\hosts"
#the address I want for the sites
redirect="0.0.0.0"
#the websites that I will set the address for
website_list=["portal.citidirect.com","www.bcinet.nc","secure.banque-tahiti.pf","www.bancatlan.hn","www.bancentro.com.ni","www.davivienda.com.sv","www.davivienda.cr","cmo.cibc.com","www.bi.com.gt","empresas.banistmo.com","online.belizebank.com","online.westernunion.com","archive.clickatell.com"]

#continuous loop
while True:
    with open(hosts_path,'r+') as file:
        content=file.read()
#for each of the websites in the list above make sure they are in the host file with the correct address
        for website in website_list:
            site=redirect+" "+ website
#here is where I have an issue, if the website is in the host file but with the wrong address I want to write over the line, instead the program is adding it to the end of the file
            if website in content:
                if site in content:
                    pass
                else:
                    file.write(site)
            else:
                file.write("\n"+site)
    time.sleep(300)

    os.system('ipconfig /flushdns')
3
  • 1
    It's much easier to write the changed lines to a new file, then rename the file to the old name when you're done. It's very tricky to update an existing file in-place. Commented Oct 5, 2017 at 1:43
  • The issue here is that you are reading the entire file, and then scanning the data. Of course, this problem can still be solved using this approach, but a faster and easier approach would be to scan the file line by line Commented Oct 5, 2017 at 2:04
  • Thanks for the responses. John Gordon I like the idea of using another file. Commented Oct 5, 2017 at 21:10

3 Answers 3

1

You need to read the file into a list, then changes the index of the list if it needs to be, then writes the list back to the file. What you are doing was just writing to the end of the file. You can’t change a file directly like that. You need to record the changes in a list then write the list. I ended up having to re-write a lot of the code. Here's the full script. I wasn't sure what the os.system('ipconfig /flushdns') was accomplishing, so I removed it. You can easily add it back where you want.

#!/usr/bin/env python3.6

import time

hosts_path = r"C:\\Windows\\System32\\drivers\\etc\\hosts"
redirect = "0.0.0.0"
website_list = [
    "portal.citidirect.com",
    "www.bcinet.nc",
    "secure.banque-tahiti.pf",
    "www.bancatlan.hn",
    "www.bancentro.com.ni",
    "www.davivienda.com.sv",
    "www.davivienda.cr",
    "cmo.cibc.com",
    "www.bi.com.gt",
    "empresas.banistmo.com",
    "online.belizebank.com",
    "online.westernunion.com",
    "archive.clickatell.com"]


def substring_in_list(the_list, substring):
    for s in the_list:
        if substring in s:
            return True
    return False


def write_websites():
    with open(hosts_path, 'r') as file:
        content = file.readlines()
    for website in website_list:
        site = "{} {}\n".format(redirect, website)
        if not substring_in_list(content, website):
            content.append(site)
        else:
            for line in content:
                if site in line:
                    pass
                elif website in line:
                    line = site
    with open(hosts_path, "w") as file:
        file.writelines(content)


while True:
    write_websites()
    time.sleep(300)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for taking the time to respond. I like how you separated it into a separate function.
You're welcome. Functions are just good practice. Always glad to help!
0

So, you're going to assign the same IP address to every site that doesn't appear in your websites list?

The following would replace what's inside your outermost while loop:

# Read in all the lines from the host file,
# splitting each into hostname, IPaddr and aliases (if any),
# and trimming off leading and trailing whitespace from
# each of these components.
host_lines = [[component.strip() for component in line.split(None, 2)] for line in open(host_path).readlines()]

# Process each of the original lines.  
for line in host_lines:
    # Is the site in our list?
    if line[1] in website_list:
        # Make sure the address is correct ...
        if line[0] != redirect:
            line[0] == redirect

        # We can remove this from the websites list.
        website_list.remove(line[1])

# Whatever sites are left in websites don't appear
# in the hosts file.  Add lines for these to host_lines
host_lines.extend([[redirect, site] for site in website_list])

# Write the host_lines back out to the hosts file:
open(hosts_path, 'w').write("\n".join([" ".join(line) for line in host_lines]))

The rightmost join glues the components of each line back together into a single string. The join to the left of it glues all of these strings together with newline characters between them, and writes this entire string to the file.

I have to say, this looks like a rather complicated and even dangerous way to make sure your hosts file stays up-to-date and accurate. Wouldn't it be better to just have a cron job scp a known-good hosts file from a trusted host every five minutes instead?

1 Comment

This is for a temporary solution to block a few websites on a few machines while we work on getting a device implemented that will handle it in the future. I like the idea of using a separate file.
0

I ended up mixing some of the responses to create a new file to replace the current host file using functions as shown below. In addition to this code I am using pyinstaller to turn it into an exe then I setup that exe to run as a auto-start service.

#!/usr/bin/env python3.6

import os
import shutil
import time

temp_file = r"c:\temp\Web\hosts"
temp_directory="c:\temp\Web"
hosts_path = r"C:\Windows\System32\drivers\etc\hosts"
websites = ('''# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#   127.0.0.1       localhost
#   ::1             localhost
0.0.0.0 portal.citidirect.com
0.0.0.0 www.bcinet.nc
0.0.0.0 secure.banque-tahiti.pf
0.0.0.0 www.bancatlan.hn
0.0.0.0 www.bancentro.com.ni
0.0.0.0 www.davivienda.com.sv
0.0.0.0 www.davivienda.cr
0.0.0.0 cmo.cibc.com
0.0.0.0 www.bi.com.gt
0.0.0.0 empresas.banistmo.com
0.0.0.0 online.belizebank.com
0.0.0.0 online.westernunion.com
0.0.0.0 archive.clickatell.com''')


def write_websites():
    with open(temp_file, 'w+') as file:
        file.write(websites)


while True:
    if not os.path.exists(temp_directory):
        os.makedirs(temp_directory)
    try:
        os.remove(temp_file)
    except OSError:
        pass

    write_websites()

    try:
        os.remove(hosts_path)
    except OSError:
        pass

    try:
        shutil.move(temp_file,hosts_path)
    except OSError:
        pass

    os.system('ipconfig /flushdns')
    time.sleep(300)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.