WORK/✍🏻 기록

원격접속 툴 제작

2024. 4. 11. 11:19
목차
  1. 0. 제작동기
  2. 1. 개발환경
  3. 2. 간단한 로직설명
  4. 3. 상세설명
  5. 1) 내정보
  6. 2) 서버구분
  7. 3) 툴을 통해 원격데스크톱열기 & 종료체크
  8. 4) .py -> exe 변환
  9. 5) 업데이트파일 만들기
  10. 4. 전체코드

0. 제작동기

회사에 웹서버가 있는데

여기에 배포를 하기도 하고 스케줄러를 켜기도 하는 등 

팀원들이 자주 들락날락 하는 곳이다

 

문제는 누군가가 접속중인지 알 수 없었고

사용중인 누군가가 강제 종료 당하는 일이 일수였다.

그래서 강제 종료당하셔서 빡친 팀장님이나 과장님이

사용할때 좀 물어보고 사용하자고 하셔서 

팀원들이 '혹시 웹서버 접속하신분~ DB서버 접속하신분~' 이렇게 물어보기 시작하면서 ㅋㅋㅋㅋ

좀 줄어들긴 했으나 문제는 팀장님 과장님이 안물어보고 하시네,,?

 

그리고 매번 물어보는것도 골때린다고 생각했다.

그래서 누가 접속중인지를 알려주는 툴을 만들어야겠다 결심했다.

 

 

1. 개발환경

빠른 제작을 위해 개발은 python으로 했다.

db는 mariaDB를 사용했고

ui는 tkinter을 사용했다.

배포,업데이트 관련은 git을 사용했다

2. 간단한 로직설명

로직은 단순했다.

 

접속시

현재 접속한 사람이 있다면 누구인지 알려주고

예를 눌으면 강제접속

아니요는 취소

 

접속한 사람이 없으면 접속을 바로 진행하는데 접속시 내가 누군지 DB에 기록했고

 

종료시 DB에 기록하는 방식이다.

 

3. 상세설명

1) 내정보

내 정보같은경우는 디렉터리내에 user정보를 담은 메모장파일을 하나 두었다

여기서 이름을 읽어 db에 넣어주는 방식이었다.

 

2) 서버구분

여기에 추가적으로 원격 데스크톱을 사용시

원격접속 주소를 알아야지 접속을 하거나

콤보박스에 기록이 저장되어있다한들

주소만보고 이게 무슨 서버인지 구분을 해야 했어서 좀 불편했다

뭐가뭐야?

 

이를 해결하고자 DB에 서버 정보도 저장하여

서버명만 보고 접속 할 수 있도록 하였다.

 

3) 툴을 통해 원격데스크톱열기 & 종료체크

툴에서 원격데스크톱을 열기위해

원격데스크톱을 열어주는 mstsc 실행 명령어를 사용했다

종료를 체크하는 기능을 어떻게 구현해야할지가 좀 어려웠는데

 

원격데스크톱을 실행시

실행된 원격데스크톱의 pid를 저장한다.

그 pid를 반복문으로 계속 검색을 한다.

그럼 실행중일때에는 당연히 실행중이기때문에 해당 pid가 계속 검색되지만

종료된다면 검색이 되지 않을테고,

그때 반복문을 탈출시켜

종료로직을 실행시키게 했다.

import subprocess
import time
from dbterm import termremo



def openremote(hostaddress, serverport, myname, conntype):
    try:
        server_address = hostaddress
        server_port = serverport

        # MSTSC 실행 명령어
        mstsc_command = f"mstsc /admin /v:{server_address}:{server_port}"

        # MSTSC 실행
        mstsc_process = subprocess.Popen(mstsc_command, shell=True)

        # 원격 데스크톱 연결의 PID 찾기
        while True:
            try:
                # MSTSC 프로세스의 상태 확인
                if mstsc_process.poll() is not None:
                    break
                
                # MSTSC 실행 중인 프로세스의 PID 찾기
                result = subprocess.run(
                    'wmic process where "CommandLine like \'%mstsc%\' and not CommandLine like \'%wmic%\'" get ProcessId /format:value',
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True
                )
                output = result.stdout.strip()
                rdp_pid = int(output.split('=')[1])

            except ValueError:
                # 정수로 변환할 수 없는 경우 계속 시도
                pass
    except IndexError:
        pass
    finally:
        print(f"MSTSC 프로세스가 종료되었습니다")
        termremo(myname, conntype)

if __name__ == "__main__":
    openremote()

 

4) .py -> exe 변환

라이브러리를 따로 설치 할 필요없 팀원들이 이툴을 바로 사용하려면 

exe파일로 변환해야했다.

 

https://jwinjection.tistory.com/152

 

여러 모듈이 있는 python 실행파일만들기

하나의 py파일에서 여러 모듈(py)을 import 해서 사용하는 경우 1. pip install cx_Freeze 설치해야함 2. setup.py생성후 내용작성해야함 3. 이후 터미널창에서 python setup.py build 입력하면 exe파일 생성됨 setup.py

jwinjection.tistory.com

 

파이썬프로젝트를 exe로 변환했다

 

5) 업데이트파일 만들기

우리회사는 BonoboGit을 사용한다.

그래서 git에 배포파일을 등록한다음

최신 파일로 update해주는 batch파일을 작성했다.

기존꺼 제거하고 깃에서 클론받아서 최신껄로 복붙해주는 로직이다

@echo off
del /f main.exe
del /f python3.dll
del /f python311.dll
rmdir /s /q lib

git clone -b exebranch --single-branch http://git주소.git
cd CHECKSERVER
cd remote

move lib ../../
move main.exe ../../
move python3.dll ../../
move python311.dll ../../
cd ../../
rmdir /s /q CHECKSERVER

 

 

 

4. 전체코드

 

comp.py

from dbsel import dbsel
from dbconn import conn
from openremote import openremote
import tkinter as tk
from tkinter import messagebox




def comp(myname,serverinfo):

    dbtype = serverinfo[0]
    dbname = serverinfo[1]
    sel = dbsel(dbtype)[0]
    conneteduser = sel[1]
    servertype = sel[2]
    state = sel[3] 
    hostaddress = serverinfo[2]
    serverport = serverinfo[3]

    if(state == 'ON'):
        msg = ('현재 ' + conneteduser + '님이 ' + dbname + '에 접속중입니다. \n강제접속 하시겠습니까?')
        result = messagebox.askquestion("확인", msg)
        if result == "yes":
            conn(myname,servertype)
            openremote(hostaddress,serverport,myname,dbtype)
        else:
            print(result)
    else:
        print("접속하겠습니다")
        conn(myname,servertype)
        openremote(hostaddress,serverport,myname,dbtype)

 

dbconn.py

import pymysql
from datetime import datetime
from dbinfo import getDbConfig

def conn(myname,servertype):
    # MariaDB 연결 정보 설정
    db_config = getDbConfig()

    # MariaDB 연결
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()

    # 현재 시간 구하기
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 현재 접속할 사용자 명
    name = myname
    conn_type = str(servertype)

    # 업데이트할 데이터
    conn_time = current_time
    conn_name = name
    conn_state = 'ON'


    # SQL 쿼리 작성하여 데이터 업데이트
    #update_query = """
    #    UPDATE remote
    #    SET conn_time = %s, conn_name = %s, conn_state = %s
    #    WHERE conn_type = %s;
    #"""

    #update_query = "UPDATE remote SET conn_time = '"+conn_time+"', conn_name = '"+conn_name+"', conn_state = '"+conn_state+"' WHERE conn_type = '"+conn_type+"'";
    update_query = "UPDATE remote SET conn_name = '"+conn_name+"', conn_state = 'ON' WHERE conn_type = '"+conn_type+"'";

    # 실제 값으로 쿼리 실행
    #cursor.execute(update_query, (conn_time, conn_name, conn_state, conn_type))
    cursor.execute(update_query)
    
    # 변경사항을 DB에 반영
    conn.commit()

    # 연결 종료
    cursor.close()
    conn.close()


if __name__ == "__main__":
    conn()

 

dbinfo.py

# dbsel.py
def getDbConfig():
    # MariaDB 연결 정보 설정
    db_config = {
        'host': 'db주소',
        'port': 포트번호,
        'user': '아이디',
        'password': '비번',
        'db': 'db명',
    }

    # 결과 반환
    return db_config



if __name__ == "__getDbConfig__":
    getDbConfig()

 

dbsel.py

import pymysql
from dbinfo import getDbConfig

# dbsel.py
def dbsel(dbtype):
    # MariaDB 연결 정보 설정
    db_config = getDbConfig()

    # type
    type = str(dbtype)

    # MariaDB 연결
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()

    # conn_type이 'gjweb'인 데이터를 선택하는 SQL 쿼리
    select_query = "SELECT * FROM remote WHERE conn_type = '"+type+"';"

    # 쿼리 실행
    cursor.execute(select_query)

    # 결과 가져오기
    result = cursor.fetchall()

    # 연결 종료
    cursor.close()
    conn.close()

    # 결과 반환
    return result



if __name__ == "__dbsel__":
    dbsel()

 

dbserversel.py

import pymysql
from dbinfo import getDbConfig

# dbsel.py
def dbserversel():
    # MariaDB 연결 정보 설정
    db_config = getDbConfig()

    # MariaDB 연결
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()

    # conn_type이 'gjweb'인 데이터를 선택하는 SQL 쿼리
    select_query = "SELECT * FROM serverinfo"

    # 쿼리 실행
    cursor.execute(select_query)

    # 결과 가져오기
    result = cursor.fetchall()

    # 연결 종료
    cursor.close()
    conn.close()

    # 결과 반환
    return result



if __name__ == "__dbserversel__":
    dbserversel()

 

dbterm.py

import pymysql
from datetime import datetime
from tkinter import messagebox
from dbinfo import getDbConfig

def show_confirmation_dialog():
    messagebox.showinfo("확인", "정상 종료되었습니다.")

def termremo(myname,conntype):
    # MariaDB 연결 정보 설정
    db_config = getDbConfig()

    # MariaDB 연결
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()

    # 현재 시간 구하기
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 현재 종료할 사용자 명
    name = myname
    conn_type = str(conntype)

    # 업데이트할 데이터
    term_time = current_time
    conn_name = name
    conn_state = 'OFF'


    # SQL 쿼리 작성하여 데이터 업데이트
    #update_query = """
    #    UPDATE remote
    #    SET term_time = %s, conn_name = %s, conn_state = %s
    #    WHERE conn_type = %s;
    #"""
    #update_query = "UPDATE remote SET conn_time = '"+conn_time+"', conn_name = '"+conn_name+"', conn_state = '"+conn_state+"' WHERE conn_type = '"+conn_type+"'";
    update_query = "UPDATE remote SET conn_name = '"+conn_name+"', conn_time = '"+term_time+"', conn_state = 'OFF' WHERE conn_type = '"+conn_type+"' and conn_name = '"+conn_name+"'";

    # 실제 값으로 쿼리 실행
    #cursor.execute(update_query, (term_time, conn_name, conn_state, conn_type))
    cursor.execute(update_query)

    # 변경사항을 DB에 반영
    conn.commit()

    # 연결 종료
    cursor.close()
    conn.close()
    show_confirmation_dialog()

if __name__ == "__main__":
    termremo()

 

getuserinfo.py

def myname():
    file_path = 'C:/remote/userinfo.txt'

    # 가능한 여러 인코딩 시도
    encodings_to_try = ['utf-8', 'cp1252', 'cp949']

    for encoding in encodings_to_try:
        try:
            with open(file_path, 'r', encoding=encoding) as file:
                lines = file.readlines()

            # 파일이 성공적으로 열렸을 때
            break
        except UnicodeDecodeError:
            print(f"인코딩 '{encoding}'으로 파일을 열 수 없습니다.")

    # 이름 추출
    for line in lines:
        if 'username :' in line:
            name = line.split(':')[-1].strip()
            print("이름:", name)

    return name

if __name__ == "__myname__":
    myname()

 

main.py

from tkinter import Tk, Canvas, ttk,Label, messagebox
from dbserversel import dbserversel
from getuserinfo import myname
from comp import comp

#pip install cx_Freeze 설치해야함
#setup.py생성후 내용작성해야함
#이후 터미널창에서 python setup.py build 입력하면 exe파일 생성됨


lst = dbserversel()
myname =myname()

svlist = [item[1] for item in lst]

def platform():
    selected_index = combo.current()
    if selected_index >= 0 and selected_index < len(lst):
        selected_data = lst[selected_index]
        #messagebox.showinfo(title="선택한 서버 정보", message=str(selected_data))
        comp(myname,selected_data)
    else:
        messagebox.showinfo(title="오류", message="올바른 서버를 선택하세요.")

window = Tk()
window.title("Server Selector")  # 창 제목 추가

# 위쪽 여백
top_space = Canvas(window, height=10)
top_space.pack()

# 텍스트 레이블
info_label = Label(window, text="내정보 : "+ myname, font=('Arial', 16))
info_label.pack(pady=5)  # 여백 추가

# 콤보박스 스타일 설정
style = ttk.Style()
style.configure("TCombobox.field",padding=(5, 5, 5, 5),  font=('Arial', 20))

# 콤보박스
combo = ttk.Combobox(window, state="readonly", style="TCombobox", width=20,height=10)  # width 옵션으로 폭 조절
combo['values'] = svlist
combo.current(0)
combo.pack(padx=10, pady=20, anchor="n")  # 여백 조절 및 위치 조정

# 버튼
action = ttk.Button(window, text="접속하기", command=platform, width=20)
action.pack(side="bottom", pady=20)  # 버튼 아래쪽에 배치

# 버튼의 크기 조절 (padding 옵션 활용)
style.configure("TButton", padding=(10, 5, 10, 5))


# 가운데 정렬
combo.pack(side="top")
action.pack(side="top")

# 창 크기 조절
window.geometry("250x200")  # 필요한 크기로 변경
window.mainloop()

 

openremote.py

import subprocess
import time
from dbterm import termremo



def openremote(hostaddress, serverport, myname, conntype):
    try:
        server_address = hostaddress
        server_port = serverport

        # MSTSC 실행 명령어
        mstsc_command = f"mstsc /admin /v:{server_address}:{server_port}"

        # MSTSC 실행
        mstsc_process = subprocess.Popen(mstsc_command, shell=True)

        # 원격 데스크톱 연결의 PID 찾기
        while True:
            try:
                # MSTSC 프로세스의 상태 확인
                if mstsc_process.poll() is not None:
                    break
                
                # MSTSC 실행 중인 프로세스의 PID 찾기
                result = subprocess.run(
                    'wmic process where "CommandLine like \'%mstsc%\' and not CommandLine like \'%wmic%\'" get ProcessId /format:value',
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True
                )
                output = result.stdout.strip()
                rdp_pid = int(output.split('=')[1])

            except ValueError:
                # 정수로 변환할 수 없는 경우 계속 시도
                pass
    except IndexError:
        pass
    finally:
        print(f"MSTSC 프로세스가 종료되었습니다")
        termremo(myname, conntype)

if __name__ == "__main__":
    openremote()

 

setup.py

from cx_Freeze import setup, Executable
import sys

buildOptions = {
	"packages":[
    	'subprocess','pymysql','datetime','time','os','win32gui', 'win32con',"tkinter"
    ],
    "excludes":[
    	
    ]
}
 
exe = [Executable('main.py', base='Win32GUI',icon="icon.ico")]
 
setup(
    name='main',
    version='1.0',
    author='me',
    options = dict(build_exe = buildOptions),
    executables = exe
)

 

userinfo.txt

username : 이재원
반응형

'WORK > ✍🏻 기록' 카테고리의 다른 글

식권관리 키오스크 만들기(1) - 웹페이지 제작  (0) 2024.12.31
Google Sheets 활용기  (0) 2024.07.03
VSCode 스니펫, 자동완성 키워드 생성  (1) 2024.04.16
리액트 컴포넌트화  (0) 2024.04.11
Redmine 활용기  (0) 2024.03.25
  1. 0. 제작동기
  2. 1. 개발환경
  3. 2. 간단한 로직설명
  4. 3. 상세설명
  5. 1) 내정보
  6. 2) 서버구분
  7. 3) 툴을 통해 원격데스크톱열기 & 종료체크
  8. 4) .py -> exe 변환
  9. 5) 업데이트파일 만들기
  10. 4. 전체코드
'WORK/✍🏻 기록' 카테고리의 다른 글
  • Google Sheets 활용기
  • VSCode 스니펫, 자동완성 키워드 생성
  • 리액트 컴포넌트화
  • Redmine 활용기
이재원
이재원
이재원
깃든블로그
이재원
유튜브
깃허브
전체
오늘
어제
글쓰기 관리
  • 분류 전체보기 (453)
    • WORK (11)
      • ✍🏻 기록 (8)
      • PLC (1)
    • DevOps (30)
      • 🛠️ CICD (9)
      • 🐳 Docker & Kubernetes (12)
      • 📡 AWS (3)
      • 🌌 Git (6)
    • 웹 개발 (198)
      • 🖥️ HTML&CSS (11)
      • 🌐 JavaScript (39)
      • 🍃 SpringBoot (51)
      • 🎆 JSP (15)
      • 🐍 Python (16)
      • ⚛️ React (15)
      • #️⃣ TypeScript (15)
      • 🧊 ThreeJS (13)
      • 🟩 Node.js (16)
      • 🚨 Error Log (7)
    • 서버&백엔드 (100)
      • 🔥 JAVA (51)
      • 🗃️ DataBase (21)
      • 🐧 Linux (21)
      • 🖥️ Windows (7)
    • AI (6)
      • 🤖 딥러닝 (6)
    • 앱 개발 (1)
      • 📱 Flutter (1)
      • ReactNative (0)
    • 컴퓨터 과학 (71)
      • 🀰 디자인패턴 (10)
      • 🔢 자료구조 (11)
      • 🛜 네트워크 (12)
      • 🖥️ 운영체제 (1)
      • 🔆 프로그래밍 (5)
      • 💯 코테 (32)
    • 개인프로젝트 (4)
      • 🤪 forfun (2)
      • 💼 포트폴리오 (1)
      • 🍎 MacBook (1)
    • 자격증 (1)
      • 💯 OPIC (0)
      • 자격증 (1)
    • 꿀팁 (9)
      • ✨ 유용한 사이트 (8)
      • 📙 티스토리 (1)
    • 여행 (1)
      • ✈️ 해외여행 (1)
      • 🗺️ 국내여행 (0)
    • 음식 (6)
      • 🏰 맛집 (5)
      • 🍰 요리 (1)
    • 일상 (4)
      • 🎨 만들기 (1)
      • 🛒 쇼핑 (2)
      • 👟 운동 (1)
    • 유튜브 (7)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 양평역
  • java
  • springboot
  • 까르띠에
  • 인사동
  • 키오스크 공익
  • 이자카야
  • 티스토리챌린지
  • 맛집
  • 존맛
  • 식권관리
  • 한식
  • 사케
  • 영등포구청
  • 코테
  • 청담메종
  • 가성비
  • 이천
  • 러닝
  • 안국역
  • JPA
  • nestjs
  • 키오스크
  • 역삼
  • 한강
  • 오블완
  • 코딩테스트
  • 키오스크공익
  • thymleaf
  • 스프링부트
반응형
이재원
원격접속 툴 제작
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.