이 포스트는 위의 Dustin York 의 Best Practices for Instant Messaging at Work 내용을 ChatGPT 를 통해 요약하였습니다.
- 직장내 인스턴트 메신저 사용에 대한 모범 사례는 다음과 같습니다.
slack
1. 목적과 용도를 명확히 이해하세요: 인스턴트 메시징은 실시간 소통과 빠른 결정에 유용하지만, 전화나 이메일 등 다른 커뮤니케이션 도구와는 목적과 용도가 다릅니다. 간단한 질문, 업무 업데이트, 미팅 일정 확인 등의 일상적인 대화에 사용하되, 복잡한 주제나 중요한 결정에는 더 적합한 도구를 사용하는 것이 좋습니다.
2. 적절한 메시지 전달 시기: 인스턴트 메시징은 실시간으로 이루어지지만, 상대방이 바쁠 수도 있으므로 메시지를 전달할 때 적절한 시간을 선택해야 합니다. 업무 시간에 다른 사람을 방해하지 않도록 주의하고, 긴급한 문제가 아니라면 비즈니스 시간 외에는 보내지 않는 것이 좋습니다.
microsoft Teams
3. 명확하고 간결한 메시지 작성: 인스턴트 메시징은 일반적으로 짧은 메시지를 주고받기 때문에 명확하고 간결하게 작성하는 것이 중요합니다. 불필요한 세부사항을 제거하고, 필요한 정보를 명확하게 전달하세요. 길고 복잡한 메시지는 효율성과 이해도를 저해할 수 있습니다.
4. 존중과 전문성 유지: 인스턴트 메시징은 빠르고 비공식적인 소통 방법이지만, 직장에서도 존중과 전문성을 유지해야 합니다. 다른 사람의 시간과 일정을 고려하고, 적절한 인사말과 단정한 언어를 사용하세요. 또한, 감정적인 반응이나 논쟁을 피하고, 긍정적이고 협력적인 태도를 유지해야 합니다.
WhatsApp for Business
5. 개인정보와 보안 유의: 인스턴트 메시징은 정보를 빠르게 공유하는 도구이므로 개인정보나 기밀 정보를 신중하게 다루어야 합니다. 개인정보를 포함한 민감한 정보는 보안을 강화한 다른 도구를 사용하는 것이 좋습니다. 또한, 악의적인 링크나 파일에 대한 조심도 필요합니다.
6. 적절한 그룹 채팅과 채널 사용: 인스턴트 메시징 플랫폼은 그룹 채팅이나 채널 기능을 제공합니다. 이를 통해 특정 프로젝트나 팀에 대한 대화를 진행할 수 있습니다. 필요한 경우 적절한 그룹 채팅을 만들고 관련 인원들을 초대하여 커뮤니케이션의 효율성을 높일 수 있습니다.
Zoho Cliq
7. 기록과 검색 가능성: 인스턴트 메시징은 대화의 기록을 남기기 때문에 필요한 정보를 나중에 찾을 수 있습니다. 필요한 정보를 빠르게 검색하고 참조할 수 있는 방법을 익히고, 중요한 결정이나 약속은 다른 도구에도 기록하는 것이 좋습니다.
8. 효과적인 알림 관리: 인스턴트 메시징은 즉각적인 알림을 제공하기 때문에 알림 관리가 중요합니다. 중요한 메시지에 대해서만 알림을 받도록 설정하고, 직장 외의 시간에는 알림을 꺼두는 등 개인의 작업 흐름에 맞춰 알림을 관리하세요.
Mattermost
9. 비상 상황에서의 사용: 인스턴트 메시징은 긴급한 상황에서 유용할 수 있습니다. 하지만 심각한 긴급 사태에 대해서는 더욱 빠른 응답이 필요하므로, 전화나 대면 소통을 우선으로 고려하는 것이 좋습니다. 비상 시나리오에 대비하여 대체 커뮤니케이션 방법을 항상 알아두는 것이 좋습니다.
이러한 모범 사례를 따르면 인스턴트 메시징을 효과적으로 활용하여 직장에서의 효율성과 협업을 향상시킬 수 있습니다.
이번 포스팅에서는 Services 내 jenkins 서비스를 찾아 Status 를 Stop 으로 하고 나서, 특정 폴더 내 폴더들 및 파일들을 찾아 삭제를 하는 FolderControlCore 코드를 확인 해 본다.
Main Code - 1Main Code - 2
1. Service (0) 을 던져, 서비스를 멈추고 나서 foreach 를 실행한다. 이때 deleteFolderName 은 스트링 배열로, Main code 에 다음과 같이 선언되어 있다.
Main Code -3
2. 배열 갯수만큼 foreach 가 돌면서 folderName 이 하나씩하나씩 클래스 멤버로 설정이 되며, SearchAndDeleteFolders() 메소드를 실행 시킨다. - 예) lastStable
FolderControlCore - SearchAndDeleteFolders()
3. SearchAndDeleteFolders() 메소드 는 설정된 directoryName 으로 폴더를 우선 찾아본다. SearchDirectories() 의 결과를 folderFound 변수에 담아 Count 확인 후, DeleteDirectories() 를 호출한다.
FolderControlCore - SearchDirectories ()
4. SearchDirectories() 메소드는 .Net 에서 지원하는 Directory 클래스 내 GetDirectoreis 메소드를 사용하여 검색한다. 이때 특정 폴더 (upperDirectoryName = %Jenkins HOME%) 와 지울 폴더 (예) lastStable) 가 있는지검색 하여 검색 결과를 IEnumerable<string> folderFound 로 전달한다.
FolderControlCore - DeleteDirectories()
5. DeleteDirectories() 메소드에서는 전달받은 폴더 경로들(list) 을 다시 한번 CheckPath() 메소드로 string 이 파일경로 형태의 string 포멧인지를 확인한다. CheckPath() 는 True/False 값을 넘기며, 경로확인이 되었을 때 .net framework 에서 지원하는 Directory 클래스의 Delete() 메소드를 이용하여 경로(path)를 삭제한다.
FolderControlCore - CheckPath()
6. CheckPath() 는 정규 표현식으로 path 문자열을 확인 한다. .net framework 내 Regex 클래스의 IsMatch 메서드는 지정된 패턴과 경로 문자열이 일치하는지 확인하며, 일치하는 경우 메서드는 true를 반환하고, 그렇지 않은 경우 false를 반환한다.
^는 문자열의 시작을 나타냄
(([a-zA-Z]:)|(\))는 드라이브 문자와 : 또는 단일 백슬래시()와 일치하는지 확인
(\{1}|((\{1})^\)+)는 나머지 경로를 일치시키며, 백슬래시() 다음에는 , :, *, ?, <, >, ", |가 아닌 문자열의 시퀀스가 와야 하며, 이 패턴은 여러 번 반복 가능하다.
7. 각 폴더별 (예: lastStable ) 로 찾은 폴더 갯수 및 삭제한 폴더 갯수, 그리고 지워지지 않은 폴더 갯수를 로그파일에 남긴다. 갯수 위에는 폴더 경로들이 찍히며, 총 4번이 찍히게 된다.
삭제 결과로그
이렇게 foreach() loop 이 완료되면 ServiceControlCore 의 메소드인 ControlService(1) 을 호출하여 Jenkins 서비스를 재시작한다.
사실 현재 사용하는 프로그램에 대한 설명은 완료 되었지만, Jenkins 서비스를 강제 shutdown 시키는 방법보다는 safe-shutdown 시키는 방법을 권장 된다. 이 방법은 Jenkins 내 shutdown 명령어가 적용 될 때, 실행 시작이 된 프로세스가 있는지 확인 하며, 완료 후 shutdown 실행이 되는데, 이 방법을 사용하려면 프로그램 안에서 cmd 명령어를 실행 시켜 진행한다. 다음 포스팅에서 이부분에 대해 알아보려고 한다.
이 클래스를 사용하여 서비스 상태를 가지고 오고, 멈춘 뒤, 필요한 작업을 진행 하고, 마지막에 서비스를 다시 시작한다. 해당 프로그램의 배경 시나리오 포스트( https://yobine.tistory.com/582 ) 에서 작성 된 프로그램의 전체 플로우와 동일하다.
Main
이번 포스팅에서는 ServiceControlCore 클래스 내 있는 Method 들을 살펴 본다. 상단에 언급했듯 이 ServiceControlCore 클래스 에서는 닷넷에서 제공하는 ServiceController 클래스를 사용하여 Jenkins 서비스의 상태를 확인하고 변경한다.
프로그램에서 제일 처음에 호출 하는 작업이 GetServices() 메소드 이다.
이 메소드는 Jenkins 서비스 상태를 확인하는 부분인데, 리턴 값은 bool 이며. 선언된 serviceName (Jenkins) 과 Services[] 로 받아온 리스트를 비교 하여, ServiceName 이 리스트에 있는지 우선 확인 하며, 서비스 이름이 Services 에 등록되어 있다면 현재 상태를 확인 하고, running 인 경우 true 를 반환한다.
services 에 등록된 service 리스트Services 리스트에서 검색 매치된 Jenkins- GetService() 메소드 - 뭔가 많아 보이지만, result = true 로 바뀌는 부분만 중요하며, 나머지는 로그 관련 스트링 전달문들이다.
- 서비스가 언제나 running 인 상태여야 프로그램이 돌기 때문에, 이부분에 대해 수정이 필요할 것 같다.
* 서비스 이름은 검색이 안되는 경우를 빼고는 해당 서비스의 상태가 stopped 인 경우에도 프로그램이 돌아야 한다. 이부분은 수정 되어야 할 사항이다. 아마 수정이 된다면, 다음 표의 내용 처럼 리턴 값을 받아 간단하게 수정이 될 수 있을 것 같다.
서비스 등록여부
서비스 상태
리턴 값
true (등록)
running
11 : (true 1, running 1)
true (등록)
stopped
10 : (true 1, stopped 0)
false (등록안됨)
stopped
20 : (false 2, stopped 0)
다음은 ControlService() 메소드 다. 이 메소드에서 서비스를 실질적으로 멈추고, 시작한다. 우선 int flag 를 인자로 , 0은 서비스 멈춤 (Stop), 1은 서비스 시작 (Start) 으로 약속된 값을 전달 받는다. 실행 중인 Jenkins 서비스(serviceName )를 멈추고(Stop) 20초 timeout 시간을 걸어주는데, 서비스가 멈추는데 걸리는 시간이 대략 최대 20초 정도여서, 멈출 때까지 대기를 하지만, 대부분 20초 전에 멈추기 때문에 대기 시간으로써는 충분한 시간이다.
ControlService() Method
ControlService() 메소드 에서 flag 값에 따라 분기가 일어나는데, if/else 가 아닌 switch 문을 사용했다. 1과 0 만이 아닌 그외의 명령어 까지 전달을 생각으로 메소드를 작성했다. 내부적으로 시작 혹은 멈추는 명령어를 전달 후, 서비스 상태를 2초마다 확인하는데, 이 메소드 이름은 CheckServiceStatus(int flag) 이다. 이 메소드 는 ControlService(int flag) 메소드에서 전달 받은 동일한 인자 flag 를 받아 GetService() 메소드를 호출하여 상태를 확인 한다.
CheckServiceStatus()
서비스를 Stop (0) 을 시켜야 하는데, GetService 의 리턴 값이 true 면, 다시 동일한 flag 값 (0) 을 가지고 재귀호출을 한다. 만약 GetSerivce 의 리턴값이 false 라면, break 가 걸리고, 서비스가 멈추었다는 로그를 남긴다.
서비스를 Start(1) 하는 내용도 동일하다. 리턴값들이 반대이지만, 동일하게 작동한다.
CMD 화면
해당 프로그램을 실행하면 위의 CMD 화면과 같이 화면에 로그들이 찍힌다. 처음에 Jenkins 서비스를 찾았고, 실행 중인 것이 확인 되어 재시작 프로세스가 시작되었다고 나오며, 서비스를 멈추게 한다. 서비스가 멈춘 후 삭제해야 할 폴더들을 각각 찾아서 삭제를 진행 하게 되며, 작업이 끝난 후에 다시 Jenkins 서비스를 실행 한다.
사용 중 인 Jenkins 버전 (2.13) 버그여서, Jenkins 를 상위 버전으로 업그레이드를 하게 되면 없어지는 현상이지만, 해당 Jenkins 에 등록되어 배포 중 인 프로젝트들도 많고 (20+), 설치 된 플러그인들 중, 해당 버전의 Jenkins에서는 잘 사용 중이지만, 상위 버전에서는 지원이 끊겨, 업데이트를 시도 했다가, 여러 문제가 발생하여 다시 현재 버전의 Jenkins 로 롤백하게 되었고, 버그 발생도 감안하며 사용 중 이다.
이 후 2.13 버전의 Jenkins 서비스엔 새로운 개발 프로젝트 등록은 하지 않기로 결정이 났고, 사용 중인 프로젝트들만 요청 시 따로 분리하는 작업을 진행 했지만 원치 않는 부서들이 더 많아서, 오류 발생 연락이 왔을 때, 바로 조치를 취해 줘야 한다.
Windows OS 를 사용하는 Slave-Node 들이 모두 off-line 으로 변경되는 오류 발생 시 취해야 하는 방법은, 인터넷 검색을 통해 다음과 같이 정리 되었다.
safeRestart : https://jenkins.url.com/safeRestart 를 실행 해 준다. CentOS 등을 사용하는 Slave-agent 들이 돌고 있을 수도 있어서 해당 agent 들의 job 이 완료되면 Jenkins 서비스 재실행이 될 수 있도록 한다. (Windows OS 의 Slave-node 로 배포 하는 프로젝트 들은 강제로 끊어줘야 한다. - 배포 job 실행 후 slave node 가 off-line 이여서 slave node 가 on-line 이 되기 를 기다리며서 job 진행 중이 되므로, safeRestart가 불가능하다.
Jenkins 서비스가 멈춘 뒤, 재시작이 진행 되었을 때, 거의 100 이면 100, 모두 오류가 나면서 서비스 재시작 실패를 하는데, 주로 다음과 같은 오류가 난다. 빨간색으로 표기한 lastStable 이라는 폴더 외에도 lastStable 이라를 폴더들 관련 ioException 오류들이 표시됩니다.
Caused by: java.io.IOException: Tried to treat 'D:\Jenkins\jobs\2. Project_Deploy\modules\etp$etp\lastStable' as a directory, but could not get a listing
at com.github.mjdetullio.jenkins.plugins.multibranch.TemplateDrivenMultiBranchProject.getConfigFiles(TemplateDrivenMultiBranchProject.java:717)
... 23 more
3. 이 상태에서는 Jenkins 서비스가 재시작을 계속 실패한다. 이때, %Jenkins HOME%/jobs 폴더 내 프로젝트 구성 폴더들 안에 있는 lastStable, lastSuccessful 폴더들을 모두 검색하여 삭제해야 한다. 이후 Jenkins 서비스를 재시작을 하면 성공적으로 서비스가 재시작 및 실행 중인 걸 확인 할 수 있다.
한동안은 위의 1,2,3 번 스텝을 slave-node 가 off-line 되는 현상이 있을 때마다 수작업으로 진행 하였는데, 서버 접속 해서 cmd 열고, 서비스 stop 명령어 전달 하고 서비스가 멈추고 나면, 3번 스텝에 언급된 폴더들을 검색하여 삭제 하고, jenkins 서비스의 재시작 누른 후.. 실행을 확인 하게 되는데, 걸리는 시간이 서버 및 네트워크 상태에 따라 족히 15분-30분까지도 걸리는 작업이다.
정규 배포 날에 해당 문제가 발생하면 이전 버전을 그냥 사용하면서 배포 가능한 시간을 기다릴 수 있지만, 오류패치 배포 등 긴급한 상황인 경우엔 15분도 너무 긴 시간이다. 그래서 클릭 한번으로 서비스 내리고, 폴더들 삭제 하고, 다시 서비스를 올리는 프로그램이 필요했고, 그래서 다음과 같이 만들게 되었다.
결론적으로는 프로그램 실행 후 모든 작업이 완료되기까지 소요되는 시간은 평균적으로 2분에서 3분정도 이며 (대부분 미만의 시간이 걸림), 이후 서비스 재시작하기까지 2-3분정도 걸린다. 빠르게 오류 발생 시 대처할 수 있게 되었다.
자 이제부터는 프로그램 코드를 공유 한다. 프로그램 언어는 c# 이며, 사용된 닷넷 버전은 4.0 이다.
서버에서 정기적으로 해당 어플리케이션(.exe) 을 실행 하여 젠킨스 서비스를 재시작하여 불시의 오류를 대비하기 위해 만드는 프로그램이여서, 콘솔앱이며 진행사항을 콘솔 및 로그 파일에 기록한다. - 하지만 불필요하게 서비스를 재시작하기 때문에, 오류 발생 시에만 사용하기로 정하였음.
이제 만들 프로그램은, 기본적으로 app.config 에 들어 있는 위의 정보들을 사용하여, 순차적으로 실행된다. Class 가 2개가 있는데 하나는 ServiceControlCore 라고 이름은 거창하지만, Jenkins 라는 서비스이름 과 타임아웃 시간을 받아 생성되는 객체다. FolderControlCore 역시 이름만 거창할 뿐, 상위 폴더 이름과 삭제할 타겟 폴더 이름을 받아, 폴더 검색, 폴더 확인 및 폴더 삭제를 진행 한다.
A. 설치된 서버 에서 Windows Services 에 등록되어 있는 특정 서비스 검색 (serviceName = Jenkins ) 후 서비스가 실행 중인지 확인한다. bool 값을 리턴받아 다음 단계를 진행한다.
B. 실행 중인 Jenkins 서비스(serviceName )를 멈춘다. 멈추고(Stop) 20초 timeout 시간을 걸어주는데, 서비스가 멈추는데 걸리는 시간이 대략 최대 20초 정도이다.
C. 프로그램 상단에 생성 시 객체에 지정 해 준 상위 폴더 (upperDirectoryName = %Jenkins HOME% ) 이름 아래에 있는 삭제할 타겟 폴더 (deleteFolderNameList ) 들을 하나 씩 전달하여 타겟 폴더 갯수 만큼 순차적으로 검색 후 삭제를 진행 한다.
D. Jenkins 서비스 (serviceName=Jenkins) 를 시작한다.( 시작 후 최대 대기 시간 20초)
E. Log 추가 (NLog 패키지 활용)
NLog 패키지 설정 및 활용에 대해서는 따로 설명은 생략 하므로 잘 작성 된 블로그를 공유한다.
const dialogPop = require('electron').remote.dialog;
// it starts with onbeforeunload with the boolean value true
let doNotCloseWindow = true;
window.onbeforeunload = (event) => {
//if the boolean value is true, the window do not close
if(doNotCloseWindow)
{
// equivalent to `return false` but not recommended
// it will prevent the window to be closed
event.returnValue = true;
//open popup
const dialogOpts = {
type: 'info',
title: 'close',
message: 'r u sure?',
buttons: ['OK', 'Cancel']
};
dialogPop.showMessageBox(dialogOpts).then((response) => {
// if OK, response.resonse = 0, else 1
if(response.response === 0){
doNotCloseWindow = false;
// it will call onbeforeunload again
window.close();
}
});
}
else
{
console.log('It should be closed')
//the window closes no matter what.. so not sure if destroy() works
window.destroy();
}
}
하드 디스크가 2개 달린 PC 에 윈10 재설치 후, 부팅 드라이브는 C 로 잘 붙어 있는데, 다른 디스크는 D 였다가 부팅만 하면 안보이네요. 컴퓨터 관리-디스크 관리-드라이브 문자 및 경로지정-드라이브문자할당 으로 D 드라이브 문자를 선택 해 주는 방법을 반복하다 다음 해결책을 발견하여 공유 합니다.
1. 명령 프롬프트를 실행합니다.
2. "diskpart"를 입력하여 diskpart에 접속합니다.
3. "list volume"을 입력하여 현재 문제를 겪고 계신 드라이브의 volume 번호를 확인합니다.
4. 문제가 있는 volume의 번호를 x라고 했을 때, "select volume=x"를 입력하여 해당 volume을 선택합니다.
- 예를 들어, 문제를 겪고 계신 volume이 volume 2인 경우, "select volume=2"를 입력하시면 됩니다.
5. "attributes volume"을 입력하여 해당 volume의 "숨김" 혹은 "기본 드라이브 문자 없음" 속성값이 "예"인 속성을 확인합니다.
6-1. "숨김" 속성의 값이 "예"인 경우, "attributes volume clear hidden"을 입력합니다.
6-2. "기본 드라이브 문자 없음" 속성의 값이 "예"인 경우, "attributes volume clear nodefaultdriveletter"를 입력합니다.
6-3. 두 속성 모두 "예"인 경우, 6-1과 6-2를 모두 입력합니다.
7. "attributes volume"을 다시 입력하여 해당 volume의 "숨김" 혹은 "기본 드라이브 문자 없음" 속성의 값이 "아니요"로 변경되었는지 확인합니다.
8. 정상적으로 변경되었다면, "exit"를 입력하여 diskpart에서 빠져나오신 후, 명령 프롬프트를 종료하시고 재부팅하여 해당 드라이브의 드라이브 문자가 자동적으로 할당되는지 확인합니다.