human time에서 unix time으로 변환 코드 예시

$ vi unix_time_to_real_time_convert.py
#! /bin/python3
from datetime import datetime, date, timedelta
from time import localtime, strftime, time


# unix time -> real time
def unix_time_to_real_time_convert(unix_time):
    local_tuple = localtime(unix_time)
    time_format= '%Y-%m-%d %H:%M:%S'
    time_str = strftime(time_format, local_tuple)
    return time_str


# real time을 unix time으로 변경 -> 2022년 07월 20일 23시 59분 59초의 real time을 unix time으로 변환
# 아래 출력 결과 : 1658329199
print(real_time_to_unix_time_convert('2022-07-20'))

unix time에서 human time으로 변환 코드 예시

$ vi real_time_to_unix_time_convert.py
#! /bin/python3
from datetime import datetime, date, timedelta
from time import localtime, strftime, time


# real time -> unix time
# (날짜를 구분할 때 '-'을 사용)
def real_time_to_unix_time_convert(real_time):
    time_year = real_time.split('-')[0]
    time_month = real_time.split('-')[1]
    time_day = real_time.split('-')[2]
    real_time = datetime(int(time_year),int(time_month), int(time_day), 23, 59, 59)
    time_str = int(real_time.timestamp())
    return time_str


# unix time을 real time으로 변경 -> 1658129100의 unix time을 real time으로 변환
# 아래 출력 결과 : 2022-07-18 16:25:00
print(unix_time_to_real_time_convert(1658129100))

  • 파이썬을 자주 사용하는 경우 if name == 'main': 을 코드에서 자주 보게 됨
    if __name__ == '__main__':
      코드
  • __name__은 모듈의 이름이 저장되는 변수
  • 파이썬 인터프리터로 스크립트 파일을 직접 실행했을 때는 모듈의 이름이 아니라 __name__에 '__main__'이 들어감
  • import로 모듈을 가져왔을 때 모듈의 이름이 '__main__'에 들어감
  • 어떤 스크립트 파일이든 파이썬 인터프리터가 최초로 실행한 스크립트 파일의 __name__에는 '__main__'이 들어감
  • __name__ == '__main__'은 프로그램의 시작점(entry point)을 의미

__name__의 대한 설명 및 예시

  • __name__는 스크립트 파일이 실행되는 상태를 파악하기 위해 사용
  • 테스트를 통해 hello.py 파일과 main.py 파일의 __name__ 변수 값이 출력
  • 파이썬에서 import로 모듈을 가져오면, 모듈 파일을 한 번 실행함 → hello 모듈을 가져오면 hello.py 안의 코드가 실행
  • hello.py의 __name__ 변수에는 'hello'가 들어가고, main.py의 __name__ 변수에는 '__main__'이 들어감
  1. hello.py 파일에 __name__ 등록
    hello.py
    print('hello 모듈 시작')
    print('hello.py __name__:', __name__)    # __name__ 변수 출력
    print('hello 모듈 끝')
  1. main.py 파일에 __name__ 등록

    main.py
    import hello    # hello 모듈을 가져옴
    
    print('main.py __name__:', __name__)    # __name__ 변수 출력
  1. main.py 파일 실행
    # 실행 결과
    $ python3 main.py
    hello 모듈 시작
    hello.py __name__: hello
    hello 모듈 끝
    main.py __name__: __main__
  1. hello.py 모듈을 main.py 파일에서 import한 예시
  1. hello.py 파일을 실행 → hello.py 스크립트가 실행되기에 hello.py가 main이 됨
    • hello.py 파일의 name 변수에는 'hello'가 아니라 'main'이 들어갑니다
      $ python3 hello.py
      hello 모듈 시작
      hello.py __name__: __main__
      hello 모듈 끝
  1. hello.py 파일을 실행하였을 때 예시

참고 URL : https://dojang.io/mod/page/view.php?id=2448

  • 파이썬으로 pip, pip3명령으로 설치 시 egg_info 실패가 발생 가능
  • egg_info 에러는 setuptools에서 에러가 발생한 것
  • setuptools을 업그레이드 하면 해결 가능

증상: pip install시 에러 Command python setup.py egg_info failed with error code 1


해결: pip setuptools 재설치 → root 권한 필요

$ pip3 install --upgrade --ignore-installed pip setuptools

pip setuptools 재설치 후 pip3로 패키지 재설치 시 정상 확인

# requests 패키지 설치
$ pip3 install requests

참고 URL : https://melonicedlatte.com/android/2018/05/21/221524.html
참고 URL : https://musclebear.tistory.com/131

  • 파이썬 WHOIS 모듈을 활용하여 도메인 등록기관(Registry)에서 관리하는 도메인의 만료 기간을 확인
  • 지속적으로 관리하지 않으면, 방심하는 사이에 도메인의 만료기간이 넘어서 서비스의 장애 발생
  • python3의 whois 모듈과 시간 모듈을 다운로드

    pip3 install python-whois
    pip3 install python-dateutil

  • WHOIS 모듈을 사용한 파이썬 코드 → 만료기간을 SLACK에 알려주는 기능 추가

    $ vi /root/whois_check.py
    import whois
    import datetime
    from dateutil.relativedelta import relativedelta
    import requests
    
    domain_lists = ['naver.com','kakao.co.kr']
    
    for domain in domain_lists:
        result = whois.whois(domain)
        expiration = result.expiration_date
        domain_txt = domain + "도메인의 만료기간이 " + str(expiration) + " 입니다."
        data = {'payload': '{"channel": "#hippo", "username": "alarm", "text": \"'+ domain_txt + '\"}'}
        response = requests.post('https://hooks.slack.com/services/[...생략...]',data=data)

  • crontab 설정

    $ cat /etc/crontab
    # 매일 아침 10시에 도메인 whois 확인
    00 10 * * * root python3 /root/whois_check.py > /dev/null 2>&1

※ 참고 URL

  • 특정 URL의 컨텐츠를 호출하는 파이썬 스크립트
  • 도메인 제외되고 URL의 Path만 있는 파일을 읽어 컨텐츠 호출
  • python3 requests get 호출 스크립트

    $ vi request_get.py
    #! /bin/python3
    import sys
    import requests
    import time
    import logging
    
    logging.basicConfig(filename='./preload.log', level=logging.INFO)
    
    def make_server_list(file):
        serverList = []
        with open(file, mode='r') as serverfile:
            for server in serverfile:
                server = server.strip('\n')
                if not server:
                    break
                serverList.append(server)
        return serverList
    
    def curl_request(server, domain, path):
        headers = {
            "host": domain,
        }
        response = requests.get("http://"+server+path, headers=headers, timeout=10)
        #response = requests.head("http://"+server+path, headers=headers, timeout=10)
        return response
    
    if __name__ == '__main__':
        domain = sys.argv[1]
        urlArgs = sys.argv[2]
        serverArgs = sys.argv[3]
    
        if len(sys.argv) != 4:
            print("Insufficient arguments")
            sys.exit()
    
        with open(urlArgs, mode='r' ) as urlfile:
            serverList = make_server_list(serverArgs)
    
            for fileLine in urlfile:
                fileLine = fileLine.strip('\n')
                #scheme=fileLine.split('://',maxsplit=1)[0]
                #domain=fileLine.split('/',maxsplit=3)[2]
                path=fileLine
                for server in serverList:
                    start = time.perf_counter()
                    response = curl_request(server, domain, path)
                    request_time = time.perf_counter() - start
                    if response.status_code == 200:
                        print("server:" + server + "\t\tpreload url : " + domain + path + "\ttime : " + str(round(request_time,3))+"s")
                        logging.info("success preload : " + server + "\tpreload url : " + domain + path + "\ttime : " + str(round(request_time,3))+"s")
                    else:
                        print("error preload : " + server + "\tpreload url : " + domain + path)
                        logging.info("error preload : " + server + "\tpreload url : " + domain + path)
                #time.sleep(1)

  • url 중에 도메인 제외한 리스트

    $ cat urllist.txt
    /test.txt

  • 서버 리스트

    $ cat serverlist.txt 
    8.8.8.8

  • 실행 예제 (실행 형식만 설명하지 실제 동작 X)

    $ python3 request_get.py test.co.kr urllist.txt serverlist.txt
    server:8.8.8.8            preload url : test.co.kr/test.txt       time : 3.037s

  • python2에서 ftplib 라이브러리 사용법 참조 가능
  • domain_list.txt 파일은 확인하고 싶은 도메인 리스트
  • python2.6으로 ftp 활용하여 특정 디렉토리에 파일 다운로드 코드 예제

    $ vi /root/ftp_file.py
    #!/bin/python2.6
    from ftplib import FTP
    import os
    from datetime import date, timedelta
    
    def file_read_line():
        read_file = []
        f = open(os.path.abspath(os.getcwd()) + '/domain_list.txt', 'r')
        while True:
            line = f.readline().strip()
            if not line:
                break
            read_file.append(line)
        f.close()
        return read_file
    
    def get_list_ftp(ftp, now_pwd, all_list=[]):
        datas = []
    
        try:
            dir_exist = ftp.cwd(now_pwd)
            data_list = ftp.nlst()
    
            for index, data_name in enumerate(data_list):
                if data_name =='.' or data_name == '..':
                    continue
                datas.append(now_pwd+data_name)
            return datas, dir_exist.split(' ')[0]
        except:
            return datas, '500'
    
    def download_path(dir_name):
        test_dir = '/' + dir_name
        if os.path.isdir(test_dir) is False:
            os.makedirs(test_dir)
        return test_dir
    
    def download_files(ftp, down_file, download_path):
        for file in down_file:
            file_name = (file.split('/')[-1])
            path_name = file.replace(file_name, '')
            ftp.cwd(path_name)
            try:
                ftp.retrbinary("RETR %s" % file_name, open(download_path+'/'+file_name,'wb').write)
            except Exception:
                print down_load_path, "/", file_name, "is downloaded failed"
    
    if __name__=="__main__":
        ftp = FTP('FTP 접속 IP')
        ftp.login('FTP ID','FTP PW')
    
        ftp.encoding='cp949'
        #print ftp.getwelcome()
    
        domains  = file_read_line()
        for domain in domains:
            all_list, down_status = get_list_ftp(ftp,'/'+domain+'/')
            if down_status != '250':
                print '/'+domain+'/ director is not exist'
                continue
            down_dir = download_path(domain)
    
            #file download
            download_files(ftp, all_list, down_dir)
    
        # ftp connect close
        ftp.quit()

  • FTP 서버에서 다운받을 디렉토리 리스트

    • a와 같이 FTP 서버에 존재하지 않는 디렉토리는 다운로드에 제외
    • 도메인을 추가하려면 마지막 줄에 추가하면 됨
      $ cat /root/domain_list.txt
      google.com
      a                             # 오류발생함으로 원래는 삭제되지만, 테스트를 위해서 투입
      baidu.com

  • FTP 추출 python2.6 스크립트 실행

    $ python2 /root/ftp_file.py

Update-alternatives로 파이썬 버전 등록 및 변경

  • 파이썬 버전 수정하기 전에 이미 등록된 것이 있는지 확인 필요
  • update-alternatives --config python 을 입력하였을 때 아무 값도 나오지 않으면 아무것도 등록된 것이 없다는 의미
    $ update-alternatives --config python

  • update-alternatives --install [symbolic link path] python [real path] number 명령어는 실행파일을 등록하는 명령어

  • 아래의 명령어 3개를 입력하면 2.7 버전과 3.6버전, 3.7버전이 update-alternatives에 등록

  • 파이썬 2.7과 3.6, 3.7이 설치되어 있어야만 update-alternatives에 등록이 가능

  • python의 설치 위치가 아래의 명령어와 다르다면 path를 변경해야만 실행이 가능

    $ update-alternatives --install /bin/python python /bin/python2.7 1
    $ update-alternatives --install /bin/python python /bin/python3.6 2
    $ update-alternatives --install /bin/python python /bin/python3.7 3

  • update-alternatives에 등록한 후 update-alternatives --config python 명령어를 입력하면 등록한 파이썬 버전을 선택하는 메뉴가 출력

    $ update-alternatives --config python
    
    There are 3 programs which provide 'python'.
    
      Selection    Command
    -----------------------------------------------
         1           /bin/python2.7
         2           /bin/python3.6
    *+ 3           /bin/python3.7
    
    Enter to keep the current selection[+], or type selection number:

  • 원하는 메뉴의 번호를 입력한 후 파이썬 버전을 확인하면 파이썬 버전을 확인 가능 → 3을 입력

  • 파이썬의 link를 따라가보면 alternatives 명령어로 설정 → alternatives가 /bin/python3.7을 가리킴

    # 선정된 python의 소프트링크 확인
    $ ls -al /bin/python
    lrwxrwxrwx 1 root root 24 Jan 18 23:50 /bin/python -> /etc/alternatives/python
    
    $ python -V
    Python 3.7.3



python3 업데이트 후 YUM 실행 시 SyntaxError: invalid syntax 에러

  • CentOS 7을 사용하던 도중에 파이썬(Python)을 2.7에서 3.7 버전으로 업그레이드를 할 필요有

  • 파이썬 3.7.3 버전을 설치한 후 /usr/bin에 있던 python 링크 또한 2.7에서 3.7 버전으로 변경

  • 아래와 같이 명령어를 실행하면 현재 파이썬 버전이 3.7이라는 것을 확인 가능

    $ python -V
    Python 3.7.3

  • 문제 발생(거의 항상 발생) → 파이썬을 3.7로 교체한 후 yum이 실행 X

    $ yum update
    File "/usr/bin/yum", line 30
      except KeyboardInterrupt, e:
                              ^
    SyntaxError: invalid syntax

  • yum이 파이썬 2.7 버전을 사용하고 있었는데 파이썬을 3.7으로 업데이트하면서 문법적 문제가 발생

  • 해결방법은 간단 → yum을 파이썬 2.7 버전에서 실행되도록 수정만 하면 됨

  • /usr/bin/yum 스크립트 내용 확인

    $ cat /usr/bin/yum
    #!/usr/bin/python
    import sys
    try:
       import yum
    except ImportError:
       print >> sys.stderr, """\
    There was a problem importing one of the Python modules
    required to run yum. The error leading to this problem was:
    
      %s
    
    Please install a package which provides this module, or
    verify that the module is installed correctly.
    
    It's possible that the above module doesn't match the
    current version of Python, which is:
    %s
    
    If you cannot solve this problem yourself, please go to
    the yum faq at:
     http://yum.baseurl.org/wiki/Faq
    
    """ % (sys.exc_value, sys.version)
       sys.exit(1)
    
    sys.path.insert(0, '/usr/share/yum-cli')
    try:
       import yummain
       yummain.user_main(sys.argv[1:], exit_code=True)
    except KeyboardInterrupt, e:
       print >> sys.stderr, "\n\nExiting on user cancel."
       sys.exit(1)

  • 가장 첫 줄 #!/usr/bin/python을 통해 python 명령어가 실행됨을 확인 가능

  • python 명령어에 대한 링크를 python3.6으로 변경해 놓았기 때문에 yum이 파이썬 3.6 환경으로 실행된 것

  • /usr/bin/yum 파일은 python2로 설정되어있기에 가장 첫 줄을 "#!/usr/bin/python2"로 변경 필요

  • vi 에디터를 이용해서 첫 번째 줄을 아래와 같이 변경

    $ vi /usr/bin/yum
    #!/usr/bin/python2
    [...아래 내용 생략]

  • /usr/bin/yum 파일 변경 이후 추가로 /usr/libexec/urlgrabber-ext-down 파일 변경 필요

  • 파이썬 2.7 버전에서 실행될 수 있도록 가장 첫 줄 #!/usr/bin/python2 변경

    $ vi /usr/libexec/urlgrabber-ext-down
    #!/usr/bin/python2
    [...아래 내용 생략]

  • yum 명령을 실행 테스트 → 정상적으로 동작

    $ yum update -y
    Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
    * base: mirror.kakao.com
    * epel: ftp.iij.ad.jp
    * extras: mirror.kakao.com
    * updates: mirror.navercorp.com
    Resolving Dependencies
    --> Running transaction check
    ---> Package bind-export-libs.x86_64 32:9.11.4-26.P2.el7_9.2 will be updated
    ---> Package bind-export-libs.x86_64 32:9.11.4-26.P2.el7_9.3 will be an update



변경한 python을 사용할 때 오류 발생

  • 파이썬에서 다음과 같은 오류(ERROR: Python headers are missing in /usr/include/python3.6m)가 발생하면 python3-dev를 통해 문제를 해결
    $ yum install python3-dev

  • tx, rx 값을 1초마다 출력 → 소수 둘째자리까지 출력
  • 1초마다 나타나는 tx와 rx데이터를 그래프로 출력 필요 → 그래프 사용 용도에 대한 고민은 필요
  • 데이터 분석에 사용하기 위한 기초 자료로 사용 예정
  • tx, rx 값 뿐만아니라 CPU, MEMORY, DISK 등도 확장 가능
  • 1초간 tx, rx 확인하는 python3 예제 코드

    #! /bin/python3
    #-*- coding: utf-8 -*-
    from subprocess import Popen
    from subprocess import os
    from subprocess import PIPE
    from datetime import datetime
    import time
    from os import sys
    import signal
    
    def common_cmd(command, args):
        cmd = command + args
          p = Popen(cmd, shell=True, stdout=PIPE)
           (ret, err) = p.communicate()
           return ret
    
    def ifconfig_cmd():
        cmd_args = "| grep 'UP mode' | awk -F ':' '{print $2}'"
        ifconfig_ports = common_cmd('ip link ', cmd_args)
        ifconfig_ports = ifconfig_ports.decode()
        return ifconfig_ports
    
    def rx_cal():
        rx_cat_cmd_args = '/sys/class/net/'
        rx_cat_cmd_args = rx_cat_cmd_args + NIC_PORT +'/statistics/rx_bytes'
        rx_bs = common_cmd('cat ', rx_cat_cmd_args)
        rx_bs = rx_bs.decode()
        return rx_bs
    
    def tx_cal():
        tx_cat_cmd_args = '/sys/class/net/'
        tx_cat_cmd_args = tx_cat_cmd_args + NIC_PORT +'/statistics/tx_bytes'
        tx_bs = common_cmd('cat ', tx_cat_cmd_args)
        tx_bs = tx_bs.decode()
        return tx_bs
    
    def handler(signum, frame):
        print("\n"+"*" * 50 + "CTRL+Z" + "*" * 50)
        print_condition(max_rx, max_tx)
        sys.exit()
    
    def print_ms(rx_max, tx_max):
        now = str(datetime.now())
        now = now.split('.')[0]
        print("%s -> rx : %.2f MB/s\t\t\t\t\t tx : %.2f MB/s" %(now, rx_max, tx_max))
    
    def print_gs(rx_max, tx_max):
        now = str(datetime.now())
        now = now.split('.')[0]
        print("%s -> rx : %.2f GB/s\t\t\t\t\t tx : %.2f GB/s" %(now, rx_max, tx_max))
    
    def print_rx_gs(rx_max, tx_max):
        now = str(datetime.now())
        now = now.split('.')[0]
        print("%s -> rx : %.2f GB/s\t\t\t\t\t tx : %.2f MB/s" %(now, rx_max, tx_max))
    
    def print_tx_gs(rx_max, tx_max):
        now = str(datetime.now())
        now = now.split('.')[0]
        print("%s -> rx : %.2f MB/s\t\t\t\t\t tx : %.2f GB/s" %(now, rx_max, tx_max))
    
    def print_condition(max_rx, max_tx):
        if ((max_rx/1024) >=1):
            if ((max_tx/1024) >=1):
                g_rx_max = max_rx / 1024
                g_tx_max = max_tx / 1024
                print_gs(g_rx_max, g_tx_max)
            else:
                g_rx_max = max_rx / 1024
                print_rx_gs(g_rx_max, max_tx)
        else:
            if ((max_tx/1024) >=1):
                g_tx_max = max_tx / 1024
                print_tx_gs(max_rx, g_tx_max)
            else:
                print_ms(max_rx, max_tx)
    
    def byte_sum(lists):
        sum = lists[0] + lists[1] + lists[2] + lists[3] + lists[4] + lists[5] + lists[6] + lists[7]
        return sum
    
    if __name__ == "__main__":
        port_list = []
        ports = ifconfig_cmd()
        port_list = ports.split('\n')
        for index, value in enumerate(port_list):
            if (value != port_list[len(port_list)-1]):
                print("[%i] : %s\t" % (index, value), end = '')
        print("[99] : exit\n", end = '')
        print("\n위에 있는 NIC 포트는 사용 중인 것입니다.")
        try:
            NIC_PORT = input("원하는nic 포트를 입력하세요 : ")
            if (NIC_PORT == "exit" or NIC_PORT == "99"):
                exit()
            max_rx = 0
            max_tx = 0
            print("1초 간격으로 출력하겠습니다.")
    
            while True:
                rx_bs1 = rx_cal()
                tx_bs1 = tx_cal()
    
                time.sleep(1)
    
                rx_bs2 = rx_cal()
                tx_bs2 = tx_cal()
    
                rx_bs = int(rx_bs2) - int(rx_bs1)
                tx_bs = int(tx_bs2) - int(tx_bs1)
    
                rx_ms = float((rx_bs /1024 / 1024))
                tx_ms = float((tx_bs /1024 / 1024))
    
                rx_max = rx_ms * 8
                tx_max = tx_ms * 8
    
                print_condition(rx_max, tx_max)
    
                if (rx_max > max_rx):
                    max_rx = rx_max
    
                if (tx_max > max_tx):
                    max_tx = tx_max
    
                signal.signal(signal.SIGTSTP, handler)
    
        except KeyboardInterrupt:
            print("\n"+"*" * 50 + "CTRL+C" + "*" * 50)
            print_condition(max_rx, max_tx)
            # 종료
            sys.exit()

  • 1초간 tx, rx 확인하는 python3 실행 결과


+ Recent posts