0

I am working to make a status page of sorts. Essentially, it will be a basic HTML page with a little CSS that displays a list of servers and a green bubble for online, red for offline. I have the page looking the way I want and my script to ping all the servers works. I achieved the bubbles by using a very simple span tag, then setting background-color to limegreen.

The Python script iterates through a list of servers and pings each one four times. Afterwards, it checks the result and prints a message to show whether or not the server is online.

The problem I have is that I can't get the two to work together. How can I use Python and BeautifulSoup to go into my HTML file and modify the style of an element based on the result of a ping?

Example: Server 1 is online and the circle is green. Server 2 goes down, the script notices a bad ping. Script then navigates to HTML and changes the span background-color for server 2 to red.

Here is the code for the python script:

# import dependencies
import os
import pandas
from bs4 import BeautifulSoup
import re
soup = BeautifulSoup(open('index.html'), 'html.parser')

# import servernames from csv, convert to list
colnames = ['SERVERNAME']
data = pandas.read_csv('Server_List.csv', names=colnames)
hostnames = data.SERVERNAME[1:].tolist()

# ping each server
for hostname in hostnames:
    # pings each server four times
    response = os.system("ping -n 4 " + hostname)
    head, sep, tail = hostname.partition('.')
    # check the response
    if response == 0:
        print('\n', flush=True)
        print(head.upper(), 'is up!\n', flush=True)
    else:
        print('\n', flush=True)
        print(head.upper(), 'is down!\n', flush=True)

Here is one of my spans:

<span class="status" style="background-color: limegreen;">

And here is my class:

.status {
    padding: 2px 11px;
    border-radius: 100%;
}
6
  • You could re-generate the whole html every time an update happens using a HTML template, like this; or see here or here for more info. BeautifulSoup is usually used for parsing and extracting information from HTML, not editing it. Commented Oct 30, 2019 at 18:43
  • @xarantolus The only problem with that solution is I need to modify each server individually. With templates, I would need to have one for every possible combination of offline and online would I not? I should have stated in the post too that I am by no means against giving up BS4 for some other library if need be. Commented Oct 30, 2019 at 18:54
  • You don't need every possible combination, but you need to check the status for each server (e.g. using if and else, as you're already doing). Instead of printing the status, you could also append the correct html (depending on your condition) to a string, then putting that into a file Commented Oct 30, 2019 at 20:08
  • I'd be totally fine with your append there, just not sure how to move it from the script to the html. Is there an easy way to do that while keeping it tied to each individual server? Commented Oct 30, 2019 at 20:09
  • You can put a replacement string into your html file, such as $$replace_this$$. Then your script reads the index.html file into a variable template at the beginning. You also define a string at the beginning to which you append your html that will be put at the position of $$replace_this$$. This html is appended for each server, aka in for hostname in hostnames: after differenciating the result, then at the end you call replace on your template string and store its result. That is the html you want. Commented Oct 30, 2019 at 20:16

1 Answer 1

1

You'll need to generate HTML dynamically.

This can be done using a template engine, but you can also do it "manually".

This is an example on how it could work:

import os
import pandas
import re

import html

# Define the template string. Could also be loaded from a file
template = """<html>
<head>
</head>
<body>
Server Status:

$$replace_this$$

</body>
</html>"""

# import servernames from csv, convert to list
colnames = ['SERVERNAME']
data = pandas.read_csv('Server_List.csv', names=colnames)
hostnames = data.SERVERNAME[1:].tolist()


html_input = ""

# ping each server
for hostname in hostnames:
    # ping server four times
    response = os.system("ping -n 4 " + hostname)
    head, sep, tail = hostname.partition('.')

    # Append server name, escape server name to prevent injection attacks (in case data contains malicious content)
    html_input += "<p>" + html.escape(hostname)

    # check the response
    if response == 0:
        html_input += "Server is <b>up</b>"
    else:
        html_input += "Server is <b>down</b>"

    html_input += "</p>\n"

html_result = template.replace("$$replace_this$$", html_input)

# Now you can use html_result for anything, such as writing it to a file.

Note that this is not the most efficient or professional method, but it probably works well enough.

Sign up to request clarification or add additional context in comments.

2 Comments

I made a few slight changes to make it work with my actual setup here and this worked beautifully. Thanks so much for the assistance! Marking this as the answer for sure!
How do I replace this for multiple variables ?

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.