Troubleshooting Dockerized Blog

This blog is a dockerized WordPress blog. I noticed that my blog site was down this morning. I couldn’t even ssh into the host. I thought it was hacked somehow. After poking it around, I got it back up and running. Here is the things I did to get it back up.

  1. When I did ping hayato-iriumi.net, I got response back.
  2. After a while, I could hit the website but it wasn’t connecting to the database.
  3. I couldn’t even ssh into the host, so I restarted it.
  4. I was able to ssh into it now, so I checked the running containers with the following command.
    docker ps -a
  5. I noticed that NGINX container was failing because it could not start because port 80 was already in use.
  6. Checked which process was using port 80 with the following command.
    sudo netstat -pna | grep 80
  7. It turned out that another instance of NGINX was hogging the port. I stopped it and disabled it with the following command.
    sudo systemctl stop nginx
    sudo systemctl disable nginx
    sudo apt remove nginx
  8. I’m not sure what installed the instance of NGINX.
  9. Restarted the host.
  10. The site came back up.

I am seeing some errors in journalctl so something else may have caused the issue. This is a very common troubleshooting for Linux users but you should know where to look to troubleshoot Linux hosted service. I may rebuild this blog host again just in case it might have been hacked.

Advanced map with Python

As I was writing Python code using map, I came across an issue. When I ran the following code, I came across an error.

import unittest


class test(unittest.TestCase):
    def func1(self, x, y):
        return x ** y

    def test_map(self):
        a = [1, 2, 3, 4]
        results = map(self.func1, a, 2)
        print(results)

I basically wanted to pass 2 for the y parameter of func1 instead of another list. Here is the error I got.

FAILED (errors=1)

Error
Traceback (most recent call last):
  File "C:\Users\hiriu\dev\hoge\test.py", line 10, in test_map
    results = map(self.func1, a, 2)
TypeError: 'int' object is not iterable

Right, the number 2 is not a collection and is not iterable. How do I solve this problem? I searched the web and I found the following solution.

import unittest
import functools

class test(unittest.TestCase):
    def func1(self, x, y):
        return x ** y

    def test_map(self):
        a = [1, 2, 3, 4]
        results = map(functools.partial(self.func1, y=2), a)
        print(list(results))

By using the functools.partial, you get to pass a fixed value to the portion of the function. Here is the output.

[1, 4, 9, 16]

Process finished with exit code 0

Update:

I found an easier way to map a fixed parameter. Here is the example. It’s more readable and maintainable.

import unittest
from itertools import repeat


class test(unittest.TestCase):
    def func1(self, x, y):
        return x ** y

    def test_map(self):
        a = [1, 2, 3, 4]
        results = map(self.func1, a, repeat(2))
        print(list(results))

Batch Processing with Python with Multithreading (Improved)

I wrote an article on how to do batch processing with multithreads in Python last week but there are things that my sample code wasn’t handling.

  • Handle results from the threaded function.
  • Handle exceptions from the threaded function.

With these 2 points in mind, I rewrote the sample code.

from concurrent.futures import ThreadPoolExecutor
from concurrent import futures
import time


def task(n):
    print(f"processing {n}")
    if n % 5 == 0:
        raise Exception("It is divisible by 5")
    time.sleep(1)
    return True


def main():
    print("Starting ThreadPoolExecutor")
    tasks = []
    fs = []
    for i in range(23):
        tasks.append(task)

    with ThreadPoolExecutor(max_workers=5) as executor:
        for i, t in enumerate(tasks):
            future = executor.submit(t, i)
            fs.append(future)
        results = futures.wait(fs)
    for result in results.done:
        if result.done():
            print(f"{result.done()}")
        if result.exception() is not None:
            print(f"Handle exception here: {result.exception()}")


if __name__ == '__main__':
    start_time = time.time()
    main()
    elapsed_time = time.time() - start_time
    print(f"Took {elapsed_time}")

Here is the output:

Starting ThreadPoolExecutor
processing 0
processing 1
processing 2
processing 3
processing 4
processing 5
processing 6
processing 7
processing 8
processing 9
processing 10
processing 11
processing 12
processing 13
processing 14
processing 15
processing 16
processing 17
processing 18
processing 19
processing 20
processing 21
processing 22
True
Handle exception here: It is divisible by 5
True
True
True
Handle exception here: It is divisible by 5
True
True
Handle exception here: It is divisible by 5
True
True
True
True
True
True
True
True
True
True
Handle exception here: It is divisible by 5
True
True
True
True
True
True
Handle exception here: It is divisible by 5
True
Took 4.017247915267944

This way, you can handle situations where you are expecting certain results from the threaded function and also exception situation. The previous sample did not have any of those, so this sample is a better one. Also it is easier to specify the number of concurrent threads.

How to Copy cat Output to Clipboard on Linux Mint

There may be times when you want to copy the output of cat command to your clipboard. cat foo.txt | pbcopy is available on macOS but how do we do something like that on Linux Mint (or Ubuntu)? xclip can be installed to accomplish that.

Install xclip.

sudo apt install xclip

By doing something like the following, you can copy the content of a text file to clipboard.

cat foo.txt | xclip -selection cliboard

This is too much typing just to copy contents from the text file. You could add the following alias in your ~/.bashrc or ~/.zshrc if you use zshell (which is my favorite shell).

alias "cs=xclip -selection clipboard"

Once you add the line, you can do source ~/.bashrc (or ~/.zshrc) and you should start to be able to use it like below.

cat foo.txt | cs

How to Install Google Chrome on Linux Mint

Linux Mint (and any Debian derivatives) does not come with Google Chrome. You can’t install it even from Software Manager. In this blog, I will show you how to install it from terminal.

Make sure you have vim installed on your machine. (sudo apt install vim)

Next create a new file under the directory.

sudo vim /etc/apt/sources.list.d/chrome.list

Paste the following source in the file.

deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main

Add the key.

wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -

Execute update.

sudo apt update

Install Google Chrome.

sudo apt install google-chrome-stable

Start Google Chrome

google-chrome

I’m not sure how you can add Google Chrome in the favorite menu yet. I will update this article when I find out.

Edit: It showed up in the menu the next day, so I am guessing it takes some time for the DE to cache the newly installed applications.

Checking DNS with dig

There are many DNS servers in the world. When you type hayato-iriumi.net in your browser, your browser goes out to your ISP’s DNS server or the specified DNS server to resolve it to the mapped IP address. (It’s a little more complicated actually but you get the idea)

When you change the A Record (IP address mapping to the name), it takes some time for it to propagate around the world. When you want to see which IP address certain domain name is resolved to, you can run the following command.

 dig +short hayato-iriumi.net

You can specify the DNS server to have it resolve the name.

dig +short hayato-iriumi.net @8.8.8.8

You should see the IP address as a result or no result if the DNS server doesn’t have the name mapped to the IP address yet. dig is a very useful command to check the DNS resolution in most of the Linux type of OS (dig is available on Linux Subsystem on Windows as well).

How to List available Shapes on OCI

Here is an easy way to list available shapes on Oracle Cloud Infrastrucuture.

oci compute shape list -c $tenancy_id --query "data[*]".{'shape:shape'} --output table

As of 6/5/2001, here is the list of available shapes on OCI.

+------------------------+
| shape                  |
+------------------------+
| BM.Standard.A1.160     |
| BM.Standard2.52        |
| BM.Optimized3.36       |
| BM.Standard.E4.128     |
| BM.Standard.E3.128     |
| BM.Standard.E2.64      |
| BM.Standard1.36        |
| VM.Optimized3.Flex     |
| VM.Standard.E4.Flex    |
| VM.Standard.E3.Flex    |
| VM.Standard.A1.Flex    |
| VM.Standard2.1         |
| VM.Standard2.2         |
| VM.Standard2.4         |
| VM.Standard2.8         |
| VM.Standard2.16        |
| VM.Standard2.24        |
| VM.Standard.E2.1       |
| VM.Standard.E2.2       |
| VM.Standard.E2.4       |
| VM.Standard.E2.8       |
| VM.Standard1.1         |
| VM.Standard1.2         |
| VM.Standard1.4         |
| VM.Standard1.8         |
| VM.Standard1.16        |
| BM.Standard.A1.160     |
| BM.Standard2.52        |
| BM.Optimized3.36       |
| BM.Standard.E4.128     |
| BM.Standard.E3.128     |
| BM.Standard.E2.64      |
| BM.Standard1.36        |
| VM.Optimized3.Flex     |
| VM.Standard.E4.Flex    |
| VM.Standard.E3.Flex    |
| VM.Standard.A1.Flex    |
| VM.Standard2.1         |
| VM.Standard2.2         |
| VM.Standard2.4         |
| VM.Standard2.8         |
| VM.Standard2.16        |
| VM.Standard2.24        |
| VM.Standard.E2.1       |
| VM.Standard.E2.2       |
| VM.Standard.E2.4       |
| VM.Standard.E2.8       |
| VM.Standard1.1         |
| VM.Standard1.2         |
| VM.Standard1.4         |
| VM.Standard1.8         |
| VM.Standard1.16        |
| BM.Standard.A1.160     |
| BM.Standard2.52        |
| BM.Optimized3.36       |
| BM.Standard.E4.128     |
| BM.Standard.E3.128     |
| BM.Standard.E2.64      |
| BM.Standard1.36        |
| VM.Optimized3.Flex     |
| VM.Standard.E4.Flex    |
| VM.Standard.E3.Flex    |
| VM.Standard.A1.Flex    |
| VM.Standard2.1         |
| VM.Standard2.2         |
| VM.Standard2.4         |
| VM.Standard2.8         |
| VM.Standard2.16        |
| VM.Standard2.24        |
| VM.Standard.E2.1       |
| VM.Standard.E2.2       |
| VM.Standard.E2.4       |
| VM.Standard.E2.8       |
| VM.Standard.E2.1.Micro |
| VM.Standard1.1         |
| VM.Standard1.2         |
| VM.Standard1.4         |
| VM.Standard1.8         |
| VM.Standard1.16        |
+------------------------+

nmtui on Ubuntu

I wanted to configure a static IP on my new Ubuntu VM on VirtualBox but when I executed…

sudo nmtui

The command was not available.

I’ve learned that installing network-manager makes nmtui available on Ubuntu.

sudo apt-get install network-manager

After installing network-manager, execute sudo nmtui and it allows you to use the UI to configure your network.