특정 포트를 사용하는 프로그램이 뭔지 알아내기

가끔 내가 사용하고자 하는 포트를 다른 프로그램이 선점하는 경우가 있다. 그 포트를 사용하는 프로그램이 무엇인지 어떻게 알 수 있을까?

windows 에서는 다음의 명령으로 가능하다.

>netstat -a -n -p tcp -b

핵심은 -b 에 있다.

-b : 연결 프로그램 정보 출력 (이 옵션을 쓸 경우 관리자 권한이어야 한다.)

-a는 모든 것을 보여주는데 보통 Listening , 대기 중인것은 생략되기 때문에 꼭 적어주어야 모든 포트 정보를 볼 수 있다.

-n 은 숫자 형태로 정보를 표시하라는 것이고 -p tcp 는 tcp 프로토콜을 사용하는 것을 보여주라는 의미이다.

 

 

 

git 2개의 branch 에 merge된 branch 들의 목록 비교 하는 방법

아래의 스크립트를 git-bash 에서 실행시키면 두 branch 간에 merge 된 branch 차이점을 볼 수 있다.
아래의 예에서는 PROD와 STG 사이에 적용된 branch 들이 차이점을 훑어볼 수 있다.

git checkout STG
 
for k in `git branch -a --no-merge | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%ci %cn" "$k"`\\t"$k"; done | sort -r > diffbranchA.txt
 
git checkout PROD
 
for k in `git branch -a --no-merge | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%ci %cn" "$k"`\\t"$k"; done | sort -r > diffbranchB.txt
 
diff diffbranchA.txt diffbranchB.txt | grep 0900

BitCoin 주소를 이용해 헌사된 Nelson Mandela 의 명언 보는 코드

Bitcoin 돈을 받을 주소를 이용해서 블록체인 속에서 사라지지 않는 영원히 기억된 문구를 만들어 낼 수 있다.

https://blockchain.info/ko/address/15gHNr4TCKmhHDEG31L2XFNvpnEcnPSQvd

다음의 블록체인 주소에 들어가면 돈을 받을 주소가 나열되어 있는데 bitcoin 의 주소값인 base58 로 인코딩된 값을 역으로 디코딩 하여 출력하면 된다.

import static org.junit.Assert.*;
 
import java.io.UnsupportedEncodingException;
 
import org.apache.commons.lang3.StringUtils;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Base58;
import org.junit.Test;
 
public class AddressDecodeTest {
 
    @Test
    public void test() throws AddressFormatException, UnsupportedEncodingException {
 
        String[] addresses = new String[] { "147qLbMuBPkhjGQjUxnizD1yGwEe18dMHn", "1AX5aSgcG2foSZpLdZD1vK6psojfBn9kwg",
                "1BceWTRrBwdivd3iC8xdwzqDnhwxfTxAsF", "1AyMMCme4dvs1AUcqQ2PcbVKYVVeC6Hkps",
                "1AcUCFbhKakvZeU8rems4aYtbjYStBRhcT", "1AX5XTatAggFnXZcawEJMHTKQCR3q6bciN",
                "1Bo1t2bNDDjhQ97D1T1E46zN7S5HHR44sp", "1AtSGJU3cTZLSVd4EvgnhmmDkdGJLinvVS",
                "1AtSGJU3dPEFVyiM2F6uDEbj5uSkAWHZiU", "1AFH5i3kaK7fEc78J1qkKhRWrMMFeuXcFf",
                "1A4UcZRARjdmHj8yLhF4iTDGGDQdqrzKY6", "1AFV8QDL4CfoqX9XhW3nGH6y7yipzpL3ty",
                "1A4e8xqe4g7dNNGYshX1wJCthVgoEwCybK", "1AcaG12FaR1AcEt4cJR7LqX3o6vTyyPaau",
                "1AFRWKXxi7JLfpvjxW3kuruW4eVG7W1NiJ", "1KubhUHhzzGcjprzrCsDtWzZEFYABtofCd",
                "1AcF19MRkLP8RPSzhpoHNU3NJVPTrsssQy", "16DLmocGtmcp7RckgywoLKnKLaRY4aV5Ka",
                "1B3pxn1mBuLQS7yr2YLcsC9VSjQj2m9Hxk", "1AFZvFuA5Pv3RTw679GfVYbAzykZqm3Ys2",
                "1AcHQwytpRKkX71DQasUk5TMw6qNED2Yqw", "15gHNr4TCKmhHDEG31L2XFNvpnEcnPSQvd",
                "15VAeb5KsRqbyNWWp7WHSACuVQahe5ngS7", "112CUyPHVEi3zyHViBzP3poagnvyUomYZ ",
                "1A8gyj9ETeGkS1hea2crNp1oJ7HfcRMuK8", "17mkD8JSfeVDx11ZumnEuKo6wVNw9mhipU",
                "1C3TPCe4pni96eQQXLFFe8LvV41qSC2KcL", "12TyUzmb4nCVVW87dsHUJCXvLWBYPuTpzB",
                "17xQY1Wan8TDFAmVtg8pe9mNDfp84YEn7r", "1BtmNAkEvWEts9is65unceNpRpgo9R2MxE",
                "16iwZjYtLBDUBxcMDvbjkX4fT6mEMGrWW ", "1CMDvFD3fgCw43u9p6EiWptaLLuz4byZGL",
        };
 
        for (String address : addresses) {
 
            byte[] decodedAddress = Base58.decode(address);
            String str = new String(decodedAddress, "UTF-8");
 
            System.out.println(str.substring(6, str.length() - 2));
        }
    }
}

자전거 브레이크 와이어 교체

지난주 자전거를 타는데 브레이크가 뭔가 풀리는 소리가 났었다. 자세히 살펴보지는 않았지만 주말에 자전거를 살펴 봐야겠다고 생각했다.

자세히 보니 브레이크 줄이 15가닥정도 되는데 2가닥 남고 끊어져 있었다. 오 이것은 파이널 데스티네이션?

인터넷 최저가 1700~2500 정도 하는 끊이었지만 동네에서 4000원 주고 사와서 고쳤다.

docker 기반으로 mariadb / mediawiki 설치하기

docker 기반으로 mariadb / mediawiki를 설치했다. 회사에 또 설치할꺼라 간단하게만 기록

windows 에 docker 설치

docker for windows 설치 하면 된다.

mariadb

설치

docker pull mariadb:latest

오오.. 가볍다.

기동

docker run –name nzMaria -e MYSQL_ROOT_PASSWORD=password -p 13306:3306 -d mariadb

-d 데몬으로 띄우기
-p 포트 매핑 – 도커 내부에서는 부조건 기본 포트로 띄우고 접속할 때의 포트 지정
-e 환경변수 – 도커 내부에서 mariadb를 띄울 때 root의 패스워드가 지정됨

설정

mysqlworkbench 로 localhost:13306 에 root / password 로 접속하여 mediawiki 용 계정 설정

mediawiki

설치

docker pull synctree/mediawiki

기동

docker 내부의 mediawiki 의 입장에서 mariadb는 어디에 있는가? HOST PC 를 경유해서 mariadb의 컨테이너에 접근해야 한다.

docker run –name nzWiki -v C:\Users\nzin4\Downloads:/downloads -e MEDIAWIKI_DB_USER=mediawiki -e MEDIAWIKI_DB_PASSWORD=ehdrmfdl -e MEDIAWIKI_DB_HOST=192.168.11.10:13306 -e MEDIAWIKI_DB_NAME=mediawiki -p 7777:80 synctree/mediawiki

-e mediawiki 가 mysql 에 접속하기 위한 환경 변수들을 설정
-p mediawiki는 docker 내부에서 80으로 뜨던 말던 외부에서는 7777로 접속
-v 외부 폴더 mount 단, 미리 docker settings 에서 share 필요

설정

mediawiki 설치가 완료되면 localhost:7777 로 접속 가능. 인스톨이 끝나면 LocalSettings.php 를 mediawiki로 옮겨 놓으라고 나온다. 파일을 docker 컨테이너 내부에 옮기기 위해서 HOST PC 의 download 경로를 컨테이너의 /downloads로 매핑 하였다.

docker exec -ti nzWiki bash

명령으로 nzWiki 컨테이너에 bash 로 접속

cp /downloads/LocalSettings.php ./

명령으로 LocalSettinngs.php 파일을 /var/www/html 로 복사

 

 

JIRA 에 BigPicture 설치

회사에서 JIRA를 사용하는데 프로젝트를 매니징 하기 위해서 BigPicture를 설치하였다.

Agile 이 항상 좋은 것일까? 아니면 내가 Agile을 잘 몰라서 그런 것일까?

해야 할 일을 순서대로 정하고 자주 deploy 할 수 있도록 해야겠다. BigPicture 사용법을 블로그에 올릴 예정.

 

Jenkins 로 돌리던 Spring Batch trigger 속도 올리기 (1분 내에 여러번 배치 돌리기)

들어가며

Jenkins로 Batch 를 돌리고 있었는데 1분에 한번씩 돌리던 배치를 10초 이내로 줄여야했다.

Jenkins는 Batch 전용 인터페이스도 아니긴 하지만 어쨌던 다른 데몬을 구현하기는 귀찮았다.  Cron이나 Quartz 도 1분 이내로 빨리 돌리는 방법은 없다. 꼼수는 존재하더라. Jenkins도 꼼수는 존재하지만.. 여튼 빠르게 인터넷을 검색했다.

일단 인터넷에 검색해보니 mkyong 님의 가이드는 존재했다. 인터넷에서 Spring 관련 글을 검색하면 나오는 그것.

정석

1
2
3
4
5
6
7
<task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" fixed-delay="5000" />
</task:scheduled-tasks>
<task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" cron="*/5 * * * * *" />
</task:scheduled-tasks>

2가지 타입이 존재하는데 위의것은 5초의 딜레이를 주는 것이고 아래것은 5초에 한번씩 돌도록 하는 것이다.
배치라면 병행해서 돌면 안되니까 위의 것으로 선택하는게 맞겠다.

그런데… 나는 가이드가 있다는 내용만 개발자에게 넘기고 개발이 완료 되었다고 해서 Merge 하고 테스트 해보니 잘 되어서 운영에 올렸다.

문제 발생

그런데 개발에서 MySQl이 에러를 내기 시작했다.
MySQL이 “Deadlock found when trying to get lock; try restarting transaction” Exception
뭐가 잘못된 것일까 운영에서도 곧 에러가 생길까? 일단 하루가 지났는데 운영에는 별 문제가 없었고 개발을 살펴보고 있다가 MySQL에서는 read 할 때 uncommited, commited, repeatable read 등 여러가지 select option 이 존재하는 것을 확인하였다.

1
2
3
4
5
<batch:job-repository id="5jobRepo"
 data-source="dataSourcePool"
 transaction-manager="transactionManager"
 isolation-level-for-create="READ_COMMITTED"
 table-prefix="BATCH_" />

그래서 Deadlock 이 걸린 원천적인 이유도 확인하지 않고
이걸 해결 하기 위해서 job-repository 의 isolation-level-for-create을 READ_COMMITED 로 바꾸는 실수를 범한다.
나중에 알게 되었지만 1분 이내의 배치 개발은 Mkyong 님의 가이드 중 2번째 것이 선택 되었고 parallel 로 돌기 시작한 것이다.

아차.. 똑같은 배치가 2번 돌때의 데이터가 무너지는 낭패가 발생할 수 있는 상황!!!

일단 LOOP 배치를 내리고 빨리 Mkyong 님의 가이드 중에서 첫번째 것을 적용하기 전에 (소슬 바꾸어야 하므로) Jenkins의 설정을 빠르게 읽어내려갔다.

그러다 JOB이 끝나면 다음 JOB을 트리거 할 수 있는데 자기 자신도 선택 할 수 있다는 사실을 알았다.

JOB과 JOB을 트리거 걸고 그 사이에 sleep 을 준 후 Jenkins 시작시에 JOB을 시작하게 하면 이보다 더 좋은 LOOP Batch 는 없을 것 같다는 생각이 들었다.

해결 방법

1. jenkins에 startup trigger plugin 설치

1-1. JOB에 시작시 실행 옵션을 지정

2. JOB 실행 완료후 POST build 에 같은 JOB을 지정

3. Execute Sheel 에 “sleep 15s” 를 추가하여서 매 JOB 사에 잠깐의 휴식시간을 줌.

개이득

만일 처음부터 Mkyong 님의 가이드 중 fixed-delay를 사용했더라면 어땠을까? 일단 sleep time이 source 에 박힌다. jenkins는 UI상에서 delay time을 조정할 수 있다.  물론 Jenkins를 이용해서 배치를 trigger 하고 있는 상황에서나 가능한 설정이지만 말이다. 유용한 툴은 언제나 유용하다.