반응형

 * 2020년 9월에 작성 된 Tool의 개발 로그입니다.

회사에서 사용하고 있는 Jenkins 가 간혹 이상 증상을 일으키는데, 그 중 하나는 Windows OS 를 사용하는 Slave-node 들이 모두 off-line 으로 변경 된다.

- 참고로 Jenkins 를 Master-Slave node 로 구성하는 내용은 다른 블로그에 많이 적혀 있으므로 여기서는 생략하며 아래 링크에 간략한 구성도 포함되어 공유한다. 

- https://velog.io/@doontagi/Jenkins-Master-Slave-%EA%B5%AC%EC%84%B1 

 

Jenkins Master / Slave 구성

젠킨스는 주로 소프트웨어 통합 서비스를 위해 사용된다. 이외에도 주기적인 빌드, 배포가 필요한 Batch Job을 수행하는데 활용될 수 있다.이 과정에서 하나의 Jenkins 인스턴스에 부하가 생길 수 있

velog.io

다시 본론으로 돌아오면,

사용 중 인 Jenkins 버전 (2.13) 버그여서, Jenkins 를 상위 버전으로 업그레이드를 하게 되면 없어지는 현상이지만, 해당 Jenkins 에 등록되어 배포 중 인 프로젝트들도 많고 (20+), 설치 된 플러그인들 중, 해당 버전의 Jenkins 에서는 잘 사용 중이지만, 상위 버전에서는 지원이 끊겨, 업데이트를 시도 했다가, 여러 문제가 발생하여 다시 현재 버전의 Jenkins 로 롤백하게 되었고, 버그 발생도 감안하며 사용 중 이다.

이 후 2.13 버전의 Jenkins 서비스엔 새로운 개발 프로젝트 등록은 하지 않기로 결정이 났고, 사용 중인 프로젝트들만 요청 시 따로 분리하는 작업을 진행 했지만 원치 않는 부서들이 더 많아서, 오류 발생 연락이 왔을 때, 바로 조치를 취해 줘야 한다.

Windows OS 를 사용하는 Slave-Node 들이 모두 off-line 으로 변경되는 오류 발생 시 취해야 하는 방법은, 인터넷 검색을 통해 다음과 같이 정리 되었다. 

  1. 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가 불가능하다. 
  2. Jenkins 서비스가 멈춘 뒤, 재시작이 진행 되었을 때, 거의 100 이면 100, 모두 오류가 나면서 서비스 재시작 실패를 하는데, 주로 다음과 같은 오류가 난다. 빨간색으로 표기한 lastStable 이라는 폴더 외에도 lastStable 이라를 폴더들 관련 ioException 오류들이 표시됩니다.
더보기
hudson.util.HudsonFailedToLoad: org.jvnet.hudson.reactor.ReactorException: java.lang.Error: java.lang.reflect.InvocationTargetException
    at hudson.WebAppMain$3.run(WebAppMain.java:244)
Caused by: org.jvnet.hudson.reactor.ReactorException: java.lang.Error: java.lang.reflect.InvocationTargetException
.....
Caused by: java.lang.Error: java.lang.reflect.InvocationTargetException
.....
Caused by: java.lang.reflect.InvocationTargetException
.....
    ... 8 more
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분도 너무 긴 시간이다. 그래서 클릭 한번으로 서비스 내리고, 폴더들 삭제 하고, 다시 서비스를 올리는 프로그램이 필요했고, 그래서 다음과 같이 만들게 되었다.

출처: https://www.csc.gov.sg/articles/how-to-build-good-software

결론적으로는 프로그램 실행 후 모든 작업이 완료되기까지 소요되는 시간은 평균적으로 2분에서 3분정도 이며 (대부분 미만의 시간이 걸림), 이후 서비스 재시작하기까지 2-3분정도 걸린다. 빠르게 오류 발생 시 대처할 수 있게 되었다.

자 이제부터는 프로그램 코드를 공유 한다. 프로그램 언어는 c# 이며, 사용된 닷넷 버전은 4.0 이다.

서버에서 정기적으로 해당 어플리케이션(.exe) 을 실행 하여 젠킨스 서비스를 재시작하여 불시의 오류를 대비하기 위해 만드는 프로그램이여서, 콘솔앱이며 진행사항을 콘솔 및 로그 파일에 기록한다. - 하지만 불필요하게 서비스를 재시작하기 때문에, 오류 발생 시에만 사용하기로 정하였음.

이제 만들 프로그램은, 기본적으로 app.config 에 들어 있는 위의 정보들을 사용하여, 순차적으로 실행된다. Class 가 2개가 있는데 하나는 ServiceControlCore 라고 이름은 거창하지만, Jenkins 라는 서비스이름 과 타임아웃 시간을 받아 생성되는 객체다. FolderControlCore 역시 이름만 거창할 뿐, 상위 폴더 이름과 삭제할 타겟 폴더 이름을 받아, 폴더 검색, 폴더 확인 및 폴더 삭제를 진행 한다. 

A.     설치된 서버 에서 Windows Services 에 등록되어 있는 특정 서비스 검색 (serviceNameJenkins ) 후 서비스가 실행 중인지 확인한다. bool 값을 리턴받아 다음 단계를 진행한다. 

B.     실행 중인 Jenkins 서비스(serviceName )를 멈춘다. 멈추고(Stop)  20초 timeout 시간을 걸어주는데, 서비스가 멈추는데 걸리는 시간이 대략 최대 20초 정도이다.

C. 프로그램 상단에 생성 시 객체에 지정 해 준 상위 폴더 (upperDirectoryName = %Jenkins HOME% ) 이름 아래에 있는 삭제할 타겟 폴더 (deleteFolderNameList ) 들을 하나 씩 전달하여 타겟 폴더 갯수 만큼 순차적으로 검색 후 삭제를 진행 한다. 

D. Jenkins 서비스 (serviceName=Jenkins)  를 시작한다.( 시작 후 최대 대기 시간 20초)

E.     Log 추가 (NLog 패키지 활용)

NLog 패키지 설정 및 활용에 대해서는 따로 설명은 생략 하므로 잘 작성 된 블로그를 공유한다.

- 참조: https://icodebroker.tistory.com/9402

 

[C#/NLOG] NLOG 사용하기

▶ NLog.config ​ ※ 상기 파일 속성을 아래와 같이 설정한다. 빌드 작업 : (없음) 출력 디렉터리에 복사 : 새 버전이면 복사 ▶ Program.cs using System; using NLog; namespace TestProject { /// /// 프로그램 /// class

icodebroker.tistory.com

더보기
  1. 프로그램 시작
  2. 서비스 확인
  3. 서비스 멈춤 여부
  4. 지운 폴더 리스트 및 개수
  5. 서비스 시작
  6. 그 외 오류

이로써 프로그램은 잘 만들어졌고, 이번 프로그램에서 작성 한 FolderControlCore 와 ServiceControlCore 에 대해서 다음에 좀더 자세히 살펴 보기로 한다.

-끝-

youp-han/Jenkins-Restart: it restarts the running Jenkins Service locally (github.com)

 

GitHub - youp-han/Jenkins-Restart: it restarts the running Jenkins Service locally

it restarts the running Jenkins Service locally. Contribute to youp-han/Jenkins-Restart development by creating an account on GitHub.

github.com

 

반응형
반응형

stackoverflow.com/questions/43687058/how-do-i-include-nuget-packages-in-my-solution-for-net-core-projects

 

How do I include NuGet packages in my solution for .Net Core projects?

With classic .Net projects, if I added a reference to a NuGet package, it would get downloaded to a packages folder and I could check that into source control along with the rest of my code. This

stackoverflow.com

sln 파일이 있는 곳에 NuGet.Config 파일을 만들어 다음 내용을 입력 후, 저장하고, 솔루션을 다시 오픈 하면 된다.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="globalPackagesFolder" value=".\packages" />
  </config>
</configuration>

반응형
반응형

    

    using RestSharp;
    using RestSharp.Authenticators;

    namespace User.Model
    {
        
        public class RestCalling
        {
            public string uri { get; set; }
            public string username { get; set; }
            public string password { get; set; }
            public string endPoint { get; set; } //"users/" + userId + "/identities.json"
            public string methodType { get; set; } //PUT, GET, POST, DELETE.

            //GET & Put & Post & Delete
            public string RestClientComm()
            {
                var _client = new RestClient(uri);
                IRestResponse result = null;
                _client.Authenticator = new HttpBasicAuthenticator(username: username, password: password);
                var request = new RestRequest(resource: endPoint, DataFormat.Json);


                switch (methodType)
                {
                    case "PUT": 
                        request.AddParameter("application/json", "\"identity\": {\"value\": \"" + "email@emailAddress" + "\"}}", ParameterType.RequestBody);
                        result = _client.Put(request);
                        break;

                    case "DELETE": 
                        result = _client.Delete(request);
                        break;

                    case "POST": 
                        request.AddParameter("application/json", "{\"identity\": {\"type\": \"email\", \"value\": \"" + "email@emailAddress"+ "\"}", ParameterType.RequestBody);
                        result = _client.Post(request);
                        break;

                    default: //GET
                        result = _client.Get(request);
                        break;

                }

                return result.Content;

            }
        }
    }

반응형
반응형


[참조]; https://msdn.microsoft.com/en-us/library/ms178473.aspx?f=255&MSPPError=-2147217396


ASP.NET 의 라이프 사이클 관련 MSDN 설명입니다. 위 내용에 들어가 있는 ASP.NET 의 Life Cycle 그림입니다. 





반응형
반응형


Windows10 환경에서 visualStudio 2010 에 SpringFramework 닷넷 버전 1.3.2 의 Schema 설치를 위한 수정된 NAnt 스크립트 공유합니다.

바뀐 부분

SOFTWARE\Microsoft\VisualStudio\10.0_Config\InstallDir"

spring-database-1.3.xsd


<?xml version="1.0" ?>
<project name="Spring.NET-Schema" default="deploy-schema">

<target name="locations"
   descriptions="Shows directories where .xsd files will be copied">

  
  <property name="vsXXXX.version" value="VS.NET 2010"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\10.0_Config\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2010 schema store -->
<readregistry property="vs2010.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="CurrentUser"
failonerror="false"/>
<echo message="VS.NET 2010 xsd install directory = ${vs2010.xml.schemas}${vsXXXX.relative.dir}"/> 

<property name="vsXXXX.version" value="VS.NET 2008"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\9.0\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2008 schema store -->
<readregistry property="vs2008.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<echo message="VS.NET 2008 xsd install directory = ${vs2008.xml.schemas}${vsXXXX.relative.dir}"/>

<property name="vsXXXX.version" value="VS.NET 2005"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\8.0\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2005 schema store -->
<readregistry property="vs2005.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<echo message="VS.NET 2005 xsd install directory = ${vs2005.xml.schemas}${vsXXXX.relative.dir}"/>

<property name="vsXXXX.version" value="VS.NET 2003"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\7.1\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\Packages\schemas\xml"/>
<!-- retrieve location of VS.NET 2003 schema store -->
<readregistry property="vs2003.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<echo message="VS.NET 2003 xsd install directory = ${vs2003.xml.schemas}${vsXXXX.relative.dir}"/>
</target>


<target name="deploy-schema"
description="Deploys the Schema to VS.Net schemas dirs. Copies VS 7.0, 7.1, 8.0, 9.0">

<!-- deploy spring schema to the VS.NET 2010 schema store -->
<property name="vsXXXX.version" value="VS.NET 2010"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\10.0_Config\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2010 schema store -->
<readregistry property="vs2010.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="CurrentUser"
failonerror="false"/>
<property name="vsXXXX.xml.schemas.notinstalled" value="true"/>
<if test="${property::exists('vs2010.xml.schemas')}">
<property name="vsXXXX.xml.schemas" value="${vs2010.xml.schemas}"/>
<call target="_deploy-schema"/>
</if>
<if test="${vsXXXX.xml.schemas.notinstalled}">
<echo message=""/>
<echo message="Failed installing schema files for VS.NET 2010."/>
<echo message=""/>
</if>    
    
<!-- deploy spring schema to the VS.NET 2008 schema store -->
<property name="vsXXXX.version" value="VS.NET 2008"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\9.0\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2005 schema store -->
<readregistry property="vs2008.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<property name="vsXXXX.xml.schemas.notinstalled" value="true"/>
<if test="${property::exists('vs2008.xml.schemas')}">
<property name="vsXXXX.xml.schemas" value="${vs2008.xml.schemas}"/>
<call target="_deploy-schema"/>
</if>
<if test="${vsXXXX.xml.schemas.notinstalled}">
<echo message=""/>
<echo message="Failed installing schema files for VS.NET 2008."/>
<echo message=""/>
</if>

<!-- deploy spring schema to the VS.NET 2005 schema store -->
<property name="vsXXXX.version" value="VS.NET 2005"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\8.0\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\..\Xml\Schemas"/>
<!-- retrieve location of VS.NET 2005 schema store -->
<readregistry property="vs2005.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<property name="vsXXXX.xml.schemas.notinstalled" value="true"/>
<if test="${property::exists('vs2005.xml.schemas')}">
<property name="vsXXXX.xml.schemas" value="${vs2005.xml.schemas}"/>
<call target="_deploy-schema"/>
</if>
<if test="${vsXXXX.xml.schemas.notinstalled}">
<echo message=""/>
<echo message="Failed installing schema files for VS.NET 2005."/>
<echo message=""/>
</if>


<!-- deploy spring schema to the VS.NET 2003 schema store -->
<property name="vsXXXX.version" value="VS.NET 2003"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\7.1\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\Packages\schemas\xml"/>
<!-- retrieve location of VS.NET 2003 schema store -->
<readregistry property="vs2003.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<property name="vsXXXX.xml.schemas.notinstalled" value="true"/>
<if test="${property::exists('vs2003.xml.schemas')}">
<property name="vsXXXX.xml.schemas" value="${vs2003.xml.schemas}"/>
<call target="_deploy-schema"/>
</if>
<if test="${vsXXXX.xml.schemas.notinstalled}">
<echo message=""/>
<echo message="Failed installing schema files for VS.NET 2003."/>
<echo message=""/>
</if>


<!-- deploy spring schema to the VS.NET 2002 schema store -->
<property name="vsXXXX.version" value="VS.NET 2002"/>
<property name="vsXXXX.xml.schemas.install.dir" value="SOFTWARE\Microsoft\VisualStudio\7.0\InstallDir"/>
<property name="vsXXXX.relative.dir" value="..\Packages\schemas\xml"/>
<!-- retrieve location of VS.NET 2003 schema store -->
<readregistry property="vs2002.xml.schemas" key="${vsXXXX.xml.schemas.install.dir}" hive="LocalMachine"
failonerror="false"/>
<property name="vsXXXX.xml.schemas.notinstalled" value="true"/>
<if test="${property::exists('vs2002.xml.schemas')}">
<property name="vsXXXX.xml.schemas" value="${vs2002.xml.schemas}"/>
<call target="_deploy-schema"/>
</if>
<if test="${vsXXXX.xml.schemas.notinstalled}">
<echo message=""/>
<echo message="Failed installing schema files for VS.NET 2003."/>
<echo message=""/>
</if>
</target>

<!-- 'private' scoped parameterised version of the 'deploy-schema' target -->


<target name="_deploy-schema" depends="_clean">

<!-- deploy schema to VS.NET XXXX schema store -->
<echo message="-------------------------------------------------------"/>
<echo message="Copying spring-objects-1.3.xsd to ${vsXXXX.version} installation."/>
<echo message="-------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-objects-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="-------------------------------------------------------"/>
<echo message="Copying spring-tool-1.1.xsd to ${vsXXXX.version} installation."/>
<echo message="-------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-tool-1.1.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
   overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-validation-1.3.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-validation-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-aop-1.1.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-aop-1.1.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-remoting-1.1.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-remoting-1.1.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-database.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-database-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-tx-1.1.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-tx-1.1.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-nms-1.3.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-nms-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-ems-1.3.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-ems-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<echo message="----------------------------------------------------------"/>
<echo message="Copying spring-nvelocity-1.3.xsd to ${vsXXXX.version} installation."/>
<echo message="----------------------------------------------------------"/>
<echo message=""/>
<copy file="spring-nvelocity-1.3.xsd" todir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}"
verbose="true"
overwrite="true"/>

<property name="vsXXXX.xml.schemas.notinstalled" value="false"/>
</target>

  <target name="_clean">
<echo message="-------------------------------------------------"/>
<echo message="Removing previously installed spring schema files"/>
<echo message="from ${vsXXXX.version} installation."/>
<echo message="-------------------------------------------------"/>
<echo message=""/>
    <delete failonerror="false">
      <fileset basedir="${vsXXXX.xml.schemas}${vsXXXX.relative.dir}">
        <include name="spring-*.xsd"/>
      </fileset>
    </delete>
  </target>
</project>


반응형

+ Recent posts