쿠...sal: computer
레이블이 computer인 게시물을 표시합니다. 모든 게시물 표시
레이블이 computer인 게시물을 표시합니다. 모든 게시물 표시

[컴][웹] StackOverflow 의 architecture

stack overflow architecture / programming stack / 스택오버플로우 구조 / 구성 /  하드웨어 구성


2018년 기준, StackOverflow 의 architecture


자세한 내용은 위 link 를 참고하자. 여기는 대략적인 내용만 적어놓는다.

H/W 구성

  • 9 Web server : ram 64GB
  • 4 Sql server : 2개의 cluster
    • Stack Overflow 용 : RAM 1.5GB / DB size 2.8TB
    • Stack Exchange, Careers, Meta 용: RAM 768GB, DB size 3.9TB
  • 2 Redis server : 
    • RAM 256GB
    • master-slave
  • 3 Tag engine servers
  • 3 ElasticSearch Server : 
    • RAM 196GB
    • load balanced
  • 2 HAProxy Servers
    • 1 live / 1 failover
  • 최고 초당 15,000 의 connection 처리

Programming Stack

  • C#
  • ASP.NET MVC
  • Dapper ORM
  • StackExchange.Redis
  • DotNetOpenAuth
  • MiniProfiler
  • Jil

[컴] 외국회사 Mock Interview

구글 인터뷰 예 / 구글 인터뷰 동영상 녹화


외국회사 Mock Interview

이 인터뷰는 mock interview 라고 한다. 아마 실제처럼 인터뷰를 진행하고 녹화한듯 하다. 그래서 정확히 그 회사의 인터뷰라고 할 수는 없겠지만, 어떤 식으로 인터뷰를 진행하는지에 대해 느껴볼 수 있을 것이다.


[웹][컴] Firefox Gecko View

겍코뷰 / gecko view 사용법 /

Gecko View

Firefox Focus 라는 모바일 app 이 있다. 처음에 Firefox 라는 이름에 Firefox app 에서 처럼 Gecko engine 을 사용하고 옵션만 바꿔 놓은줄 알았는데, WebView 를 사용했다고 한다.[ref. 1]

그런데 이번 release (2018. 10. 2) 에서는 Gecko 를 사용할것이라 한다.

WebView 의 한계

WebView 는 우리가 pc에서 쓰는 브라우저의 모든 기능을 제공하고 있지 않다. Web standard 의 일부만 지원한다. 그래서 실제로 완전한 browser 를 만들기에는 한계가 있다고 한다.
Foremost, it isn’t designed for building browsers. Despite being based on Chromium, WebView only supports a subset of web standards, as Google expects app developers to use native Android APIs, and not the Web, for advanced functionality.[ref. 1]
이런 이유로 Gecko engine 을 사용하려고 한다고 한다.

Gecko View

그런데 Gecko 는 WebView 처럼 다른 app 에서 사용할 수 있는 형태가 아니다. 그래서 이것을 WebView 처럼 여러곳에서 재사용할 수 있게 만들었는 데 이것이 Gecko View 이다.

현재 용량이 WebView(4MB) 보다 훨씬 큰 38MB(Gecko View) 정도라고 한다. 물론 계속 용량을 줄이고 있다고 한다. (참고: GeckoView in Firefox Focus)

Gecko View 의 사용법은 ref. 1에 일부 언급이 있다. 참고하자.



References


  1. Firefox Focus with GeckoView - Mozilla Hacks - the Web developer blog

[컴][웹] Medium Editor 사용해 보기



medium editor

medium site 에서 사용하는 editor 와 같은 기능을 제공한다.

장점

  • 화면에서 버튼을 이용해서 바로 추가적인 tag 를 넣을 수 있다. (underline, bold 등)
    • 버튼bar 가 아닌 bubble tip 버튼을 이용해서 편집을 하기에 좀 더 직관적인다.
  • 다양하게 확장이 가능하다.(extension)[ref. 1]

image insert

image 는 그냥 끌어다 놓으면 된다. 다만 이경우에 data:image/png 등의 모습으로 insert 된다. 이녀석은 server 단에서 image 로 변환하면 된다. 자세한 것은 아래 글을 참고하자.



local 에서 사용해보기

아래 4개의 파일을 경로에 맞춰서 local 에 넣자. 그리고 absoulte-container.html 을 실행하면 medium editor 를 사용해 볼 수 있다. 직접 demo 를 확인하고 싶다면 여기로 가자
<medium-editor>/dist/css/medium-editor.css
<medium-editor>/dist/css/themes/default.css
<medium-editor>/dist/js/medium-editor.js
<medium-editor>/demo/absolute-container.html


버튼 기능 확장

medium editor 의 버튼을 확장할 수 있다. 즉, 버튼을 추가하고, 원하는 기능을 넣을 수 있다. 자세한 사항은 아래 글에서 확인하자.

예제

아래처럼 editor의 toolbar 에 highlighter 를 추가할 수 있다.
var editor = new MediumEditor('.editable', {
    toolbar: {
        buttons: ['bold', 'italic', 'underline', 'highlighter']
    },
    extensions: {
        'highlighter': new HighlighterButton(),
        ...
    }
});

HighlighterButton class 는 위 글에서 code 를 옮겨왔다. 아래 처럼 자신이 원하는 버튼 기능을 만들면 된다.(자세한 것은 위링크를 확인하자)

rangy.init();
var HighlighterButton = MediumEditor.Extension.extend({
  name: 'highlighter',

  init: function () {
    this.classApplier = rangy.createClassApplier('highlight', {
        elementTagName: 'mark',
        normalize: true
    });

    this.button = this.document.createElement('button');
    this.button.classList.add('medium-editor-action');
    this.button.innerHTML = '<b>H</b>';
    this.button.title = 'Highlight';

    this.on(this.button, 'click', this.handleClick.bind(this));
  },

  getButton: function () {
    return this.button;
  },

  handleClick: function (event) {
    this.classApplier.toggleSelection();

    // Ensure the editor knows about an html change so watchers are notified
    // ie: <textarea> elements depend on the editableInput event to stay synchronized
    this.base.checkContentChanged();
  },

  // 파란색 함수는 이미 효과가 적용된 text 를 select 했을 때 
  // 버튼이 눌러진 모습을 표현하기 위한 것이다.
  isAlreadyApplied: function (node) {
    return node.nodeName.toLowerCase() === 'mark';
  },

  isActive: function () {
    return this.button.classList.contains('medium-editor-button-active');
  },

  setInactive: function () {
    this.button.classList.remove('medium-editor-button-active');
  },

  setActive: function () {
    this.button.classList.add('medium-editor-button-active');
  }
});



References

  1. medium-editor/src/js/extensions at master · yabwe/medium-editor · GitHub
  2. GitHub - yabwe/medium-editor-tables: Tables extension for MediumEditor

[컴][웹] jquery 를 사용하지 않는 markdown editor

마크다운 에디터 / js editor

jquery 를 사용하지 않는 markdown editor





See Also


[컴][웹] Server-Side Event(SSE)

서버 사이드 이벤트 / 폴링 / 푸쉬 메시지



Server-Side Event(SSE)

여기서는 ref. 2 에 있는 이야기의 일부를 다룬다. 되도록 ref. 2 내용 전체를 보는 것이 더 도움이 될 듯 하다.

대략적으로 이야기하면, 이녀석은 기본적으로 ajax 로 했던 polling 을 browser 가 대신해준다고 생각하면 된다. 즉, polling 을 사용했어야 하는 모든 경우에 사용할 수 있다. 그리고 polling 이 끊겼을때등에 대한 처리에 관한 설정(id 같은, ref. 2를 참고) 도 가능하기 때문에 훨씬 편리하고 좋다.

그리고 ref.2 에 보면 SSE 는 http protocol 로 만들어졌다고 한다. 그래서 이것을 실행하는 주체는 browser 안에서 layer 가 좀 다를 수는 있지만, js script 내에서 polling 을 구현한 것이랑 거의 다를 바가 없을 듯 하다. 여하튼 ref. 2 에서는 이것을 event streaming 이라고 부른다.


event streaming 을 close 하는 법


이렇게 주기적으로 browser 가 server로 부터 event 를 받아오는데, 이것을 close 하는 방법이 2가지 있다.
  • 서버에서 close 하는 법 : 
    • Content-Type 이 text/event-stream 가 아닌 response 를 보내거나
    • 200 이외의 HTTP status 를 보낸다.
  • client 에서 close 하는 법
    • source.close();
다만 이런 방법으로 Event streaming 을 끝내지 않고, 만약 network 가 끊어진 상황, 즉 browser 가 아예통신을 못하거나 한 상황에 의해 event streaming 이 끊긴 경우라면, browser 가 알아서 주기적으로 연결을 위해 시도를 한다.


message event

기본적으로 발생시키는 event 는 message event 이다. 하지만, server 의 응답에 "event" 를 정의해서 browser 로 하여금 새로운 event 를 발생시키도록 할 수 있다.
event: servertime
data: The server time...

source.addEventListener('servertime', function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
});



Response

header 조건

  1. Content-Type: text/event-stream
  2. Cache-Control: no-cache

body

  • data: data_you_want_to_put
reponse body 이 딱 data 만 있으면 된다. 다른 option 들도 존재한다.(ref. 2 참고)
data: The server time...




Security 

보안상의 이슈로 client 에서 event handler 를 구현할 때 event 의 origin 을 check 하라고 한다.[ref. 2]
source.addEventListener('message', function(e) {
  if (e.origin != 'http://example.com') {
    alert('Origin was not http://example.com');
    return;
  }
  ...
}, false);


References

  1. HTML5 Server-Sent Events
  2. Stream Updates with Server-Sent Events - HTML5 Rocks

[컴][DB] MySQL 에서 transaction 과 isolation level


MySQL 에서 transaction 과 isolation level

아래는 정리되지 않은 글이다. 정리는 추후에...

mysql 의 default isolation level

MySql 의 InnoDB 는 Repeatable-read 가 기본 isolation level 이다.

기본 sql standard

sql에서 Repeatable-read 는 아래 3가지를 만족한다.
  • dirty reads (non committed data)
  • non repeatable reads (executing the same query twice should return the same values)
  • allows phantom reads (new rows are visible).

MY SQL 의 default isolation 변경법

실행시에 --transaction-isolation=level option 을 사용하면 된다.(참고)

현재 isolation level 확인방법

-- to check the current isolation level
SHOW variables like 'tx_isolation'

isolation levels

  • SQL Server 트랜잭션 잠금 및 행 버전 관리 지침 | Microsoft Docs
  • SERIALIZABLE : REPEATABLE READ 보다 더 엄격 하다. XA transactions 이나 concurrency 와 deadlocks의 troubleshooting 을 위해서
  • REPEATABLE READ : 가장 높은 수준의 consistency(일관성)
  • READ COMMITTED : locking 에 대한 overhead 가 더 중요해서 precise consistency 와 반복적인 결과들이 덜 중요할때 사용할 수 있다.
  • READ UNCOMMITTED : READ COMMITTED 와 같다. 단 dirty read(select 가 nonlocking 된 상태로 수행된다.) 가 허용된다.(consistency 를 보장하지 않는다.)
격리 수준 커밋되지 않은 읽기 반복되지 않는 읽기 가상
READ UNCOMMITTED
READ COMMITTED 아니요
REPEATABLE READ 아니요 아니요
스냅숏 아니요 아니요 아니요
직렬화 가능 아니요 아니요 아니요
가상읽기(Phantom read)가 가능하기 때문에 만약 아래와 같은 2개의 transaction 이 동시에 실행되는 경우 transaction 1 의 첫 SELECT 와 두번째 SELECT 가 다른 결과를 같게 된다. (두번째 select 의 결과 row 가 더 많을 것이다.)
-- Transaction 1
SELECT * FROM table1
SELECT * FROM table1
-- Transaction 2
INSERT INTO table1 ...

아래와 같은 transaction 이 동시에 일어나는 경우, INSERT 가 2번 된다. 이를 막기 위해 insert 시에 index 를 지정해서 넣어주면, 같은 index 에 insert 를 피할 수 있다. 하지만 문제는 끝부분에서 중복이슈는 없지만, 중복 이슈와 상관없는 경우에도 insert 가 실패하기 때문에 문제가 될 수 있다.

그리고 상품이 2개이상이 동시에 열리는 경우 2개의 상품의 마지막투자가 같은 순간에 이뤄지면, 둘다 같은 index 를 next 로 잡아서 insert 를 할 것이고, 그것이 충돌을 일으킬 수 있다.

해결책

결국 queue 를 두는 방식으로, 즉 worker 로 넘기는 방식을 쓰기로 했다. 아무래도 그래야만 consistency 가 유지될 수 있다고 본다.
-- Transaction 3
SELECT * FROM table1 ...
-- insert depending on the result of the select
INSERT INTO table1 ... 

References

  1. Understanding MySQL Isolation Levels: Repeatable-read | Official Pythian® Blog
  2. MySQL :: MySQL 8.0 Reference Manual :: 15.5.2.1 Transaction Isolation Levels

[컴][하드웨어] GPU 의 memory bandwidth 와 VRAM



GPU 의 memory bandwidth 와 VRAM

다음은 ref. 1 의 "Memory Bandwidth, Memory Capacity" 부분을 의역한 내용이다.

----

메모리 대역폭(memory bandwidth) 는 GPU 의 VRAM 에 한번에 얼마나 많은 양을 넣고(copy to), 뺄수(copy from) 있는 지를 알려준다. 당연한 이야기지만, 같은 해상도(resolution)에서 시각효과(visual effects) 가 많을 수록 더 놓은 memory bandwidth 가 필요하다.(더 많은 data 를 한 번에 옮겨야 하니.)

VRAM 의 총용량은 GPU 의 다른 중요한 요소다. 필요한 VRAM 의 양이 현재 가능한 리소스를 넘어선다면, 게임은 계속 돌겠지만, 이 부족한 memory 부분만큼 CPU 의 main memory 를 이용하게 된다.

이것은 GPU 가 DRAM 에서 data 를 가져오게 돼서, GPU 의 VRAM 에서 가져오는 시간보다 더 오래 걸리게 된다. 결국 이것이 게임화면의 버벅임을 만들게 된다.

그래서 VRAM 의 양이 중요하긴 하지만, 일부 low-end 그래픽카드는 쓸데없이 VRAM 이 많은 경우가 있다. 즉, VRAM 이 부족해 지기 전에 다른 부분에서 bottleneck 이 걸릴 수가 있다. 그러므로 이런 경우를 방지하기 위해 benchmark 결과등을 잘 살펴서 구매를 할 필요가 있다.

---

Memory Bandwidth Specification


GPU 와 VRAM 간의 memory bandwidth 는 GDDR 의 spec. 을 확인해 보면 된다. GDDR6가 요즘 나오고 있다. 고대역폭을 위해 새롭게 만든 HBM(High bandwidth memory) 이라는 스펙도 있다. 이녀석은 GDDR6가 나오고는 경쟁력이 확실히 많이 떨어졌다.

GDDR6의 데이터 전송 속도는 최대 18Gbps로 고성능 GPU의 384비트 메모리 버스에선 864GB/s의 대역폭((18Gbps * 384bit )/ 8bit = 864GB/s)이 나온다.



References

[컴][웹]보안] KISA 웹 취약점 점검 요청


무료 취약점 점검 / 웹 취약점 점검 요청


KISA 웹 취약점 점검 요청방법


필요한 요소

  1. 중소기업 확인서
  2. 신청서(신청서 다운로드)
  3. 공문

공문에는 아래의 내용이 포함되어 있어야 합니다.
 1. 한국인터넷진흥원으로부터 웹취약점 점검 시 발생할 수 있는
    홈페이지 접속 중단, 서버 장애 등 위험성에 대해서 고지를 받았고 인지하였음
 2. 웹취약점 점검 시 홈페이지 접속 중단, 서버 장애로 인한 고객 손실 피해 등
    어떠한 경우에도 한국인터넷진흥원에 민사,형사상 책임을 묻지 않겠음

 3. 한국인터넷진흥원에서 점검한 내용은 증빙자료, 홍보 등의 수단으로 사용하지 않겠음


자세한 사항은 여기에서 전화번호 또는 이메일로 문의하면 답변해 준다.

[컴][웹][자바][스프링] Spring Boot 에서 executable war 사용



Spring Boot 에서 executable war 사용

사용이유

ref. 1 에 따르면 jsp 를 사용하려면 executable jar 로 묶어서는 안되고, .war 로 packaging 을 해야 한다고 한다.

source code

여기서는 gs-spring-boot source 를 사용할 것이다. git clone 을 통해 가져오면 된다. 그런 후에 complete folder 에 있는 소스를 사용하면 된다.
  • git clone https://github.com/spring-guides/gs-spring-boot.git

build.gradle

그래서 build.gradle 에서 bootJar 을 지우고, bootWar 을 적은후 gradlew build 를 하면 된다. 또는 enabled 속성을 이용하면 된다.


만약 2개를 build.gradle 에 적어놓는다면, gradlew bootWar 를 이용하면 된다. 그러면 아래 경로에 만들어진다.
  • <root>\build\libs\broker-sb-0.1.0-SNAPSHOT.war
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'

bootWar {
    // https://docs.gradle.org/current/userguide/war_plugin.html
    enabled = true
    baseName = 'broker-sb'
    version = '0.1.0-SNAPSHOT'
}

bootJar {
    // this determines the jar name.
    enabled = false
    baseName = 'broker-sb'    // ./build/libs/broker-sb-0.1.0.jar
    version =  '0.1.0'
}

webapp directory

아래와 같은 구조로 다음 경로에 webapp 을 만들면 된다.
  • <root>\src\main\webapp\
webapp
   + resources
   + WEB-INF
      + config
      + property
      + tags
      + views

lib에 있는 jar이 .so 등을 필요로 한다면


결과적으로 lib에 같이 넣을 수 없을 듯 하다. 실제로 executable jar / executable war 모두에서 lib 를 읽어드릴때 netsted jar 로 가정하고 읽어드렸다. 그래서 모두 아래와 같은 exception이 발생했다.

c:\a\programming\java\mm\springboot-test\complete\build\libs>java -jar mmbroker-sb-0.1.0-SNAPSHOT.war
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry WEB-INF/lib/libsigar-amd64-linux.so
        at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:108)
        at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:86)
        at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:70)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:49)
        at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:58)
Caused by: java.io.IOException: Unable to open nested jar file 'WEB-INF/lib/libsigar-amd64-linux.so'
        at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:254)
        at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:239)
        at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:103)
        ... 4 more
Caused by: java.io.IOException: Unable to find ZIP central directory records after reading 65792 bytes
        at org.springframework.boot.loader.jar.CentralDirectoryEndRecord.<init>(CentralDirectoryEndRecord.java:65)
        at org.springframework.boot.loader.jar.CentralDirectoryParser.parse(CentralDirectoryParser.java:52)
        at org.springframework.boot.loader.jar.JarFile.<init>(JarFile.java:121)
        at org.springframework.boot.loader.jar.JarFile.<init>(JarFile.java:109)
        at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:287)
        at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:262)
        at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:250)
        ... 6 more

References

  1. Spring Boot Reference Guide > 27.4.5 JSP Limitations

[컴][리눅스] systemd 사용법

sys 사용법 / init 사용법 /


systemd 사용법

commands

  • systemctl : 현재 동작중인 서비스들을 보여준다.
    • systemctl list-unit-files : 등록된 모든 service 들을 보여준다.
    • systemctl list-dependencies mariadb.service : mariadb.service 의 서비스간의 의존관계(dependecy)를 보여준다.
    • systemctl set-default <new_taget_file> : 기본 target 을 변경
    • systemctl get-default : 기본 target 을 알려준다.
    • systemctl isolate runlevel5.target : runlevel5 로 runlevel 을 변경한다.
    • service 실행
      • systemctl start foo.service
      • systemctl stop foo.service
      • systemctl restart foo.service
      • systemctl status foo.service
    • 부팅시 실행
      • systemctl enable foo.service : 부팅시 실행
      • systemctl disable foo.service : 부팅시 실행하지 않도록
  • systemd-analyze : 부팅에 소요된 시간을 알 수 있다.
    • systemd-analyze blame : 각 서비스별 초기화에 걸린 시간을 확인할 수 있다.
    • systemd-analyze plot : init 시간을 그래프로 나타내 준다. output 을 html 로 저장해서 보면 된다.
    • systemd-analyze critical-chain <service_name> : 초기화에 시간을 많이 먹는 서비스들을 보여준다.
  • systemd-cgls
  • systemd-cgtop
  • systemd-loginctl


unit file

기본적으로 /usr/lib/system 디렉토리에 Unit File 을 보관한다. 보통 .service 의 확장자(?)를 가지고 있다.

만약 기존의 unit file 을 변경하려면, 이 파일을 직접 변경하는 것보단 override 하는 것을 추천한다.[ref.1]

systemctl edit

systemctl edit mariadb
수정할 수 있다. 자세한 내용은 ref. 1, ref. 4 을 확인하자.

unit file 만들기



target

타겟(Target)은 Sys V 에 Run Level 과 비슷하다. 즉, booting 을 어느 단계까지 할 것이냐를 결정하는 것이라고 보면 된다.

target 도 아래 경로에서 확인할 수 있다.(.target 으로 되어 있다.)

  • /usr/lib/systemd/system/

default target 변경

기본적으로 runlevel*.target(symbolic link 이다.) 이 존재한다. 그래서 이것을 sysv 의 runlevel 처럼 사용하면 된다.


# systemctl set-default runlevel3.target
# systemctl get-default

isolate target

현재 target 을 바꾸고 싶으면 isolate 을 사용하면 된다. (isolate 의 의미)
# systemctl isolate runlevel5.target
예를 들어 만약 gui 를 사용하고 있는데 isolate runlevel3.target 을 하면, gui 를 닫아버리고, runlevel3.target 에 맞추게 된다.

현재 active target 확인

# systemctl list-units --type=target


References

  1. CentOS 7 Systemd 이해하기 - Voyager of Linux
  2. 서버 프로세스를 관리하는 올바른 방법 - CODEOK.NET
  3. Useful SystemD commands (hints for systemctl or systemctl vs chkconfig and service)
  4. 10.6. Creating and Modifying systemd Unit Files - Red Hat Customer Portal

[컴] 코딩 관련 youtube

dev tube / devtube / dev youtube / coding youtube / 코딩 유투브 /


코딩 관련 youtube 를 모아놓은 사이트, 데브튜브


[컴][리눅스] Linux에서 Login 실패 시 로그인 제한하기



일정 횟수 이상 실패시 제한 / 계정 잠그기


Linux에서 Login 실패 시 로그인 제한하기

리눅스에서 계정에 관한 대부분의 설정은 /etc/login.defs에서 가능

pam_tally2 로 로그인 실패시 계정 제한

PAM (Pluggable Authentication Modules)

# vi /etc/pam.d/password-auth

아래 파일을 보면 대충 어떻게 설정하는지 알 수 있다. 3번 로그인 실패하면 20분(1200초)동안 잠그게 된다.
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.

auth        required      pam_tally2.so  file=/var/log/tallylog deny=3 even_deny_root unlock_time=1200
...
account     required      pam_unix.so
account     required      pam_tally2.so

~
~
~
~


pam_tally2

user id 의 failure count 를 확인할 수 있다.
# pam_tally2 --user=my_user_id

잠겨버린 계정을 해제
# pam_tally2 --user=my_user_id --reset



pam_faillock 을 사용해서 계정 잠그기

pam_fillock 은 pam_tolly2 의 login 실패기능에 대한 기능향상 버전이다. (참고) 그래서 이녀석을 쓰면 훨씬 다양한 정보를 얻을 수 있다.

설정

아래 내용을 2개의 파일 모두에 넣으면 된다. 순서가 중요하다.

# vi /etc/pam.d/password-auth
# vi /etc/pam.d/system-auth

auth        required      pam_faillock.so preauth silent audit deny=3 unlock_time=600
auth        sufficient    pam_unix.so nullok try_first_pass
auth        [default=die] pam_faillock.so authfail audit deny=3 unlock_time=600

...

account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so
account     required      pam_faillock.so


root 계정도 잠그기

만약 root 도 일정 실패 이후에 잠그고 싶다면 even_deny_root 를 추가하면 된다.
pam_faillock.so preauth silent audit deny=3 even_deny_root unlock_time=600

sshd restart

그리고 sshd 를 restart 해줘야 한다.
systemctl restart sshd

실패한 로그인 시도 확인

faillock --user my_user_id


'faillock' 를 치면, 실패한 로그인 전체 목록을 볼 수 있다.

실패로그 삭제

user 의 인증실패로그(authentication failure log)를 삭제하려면 아래처럼 하면 된다.
faillock --user aaronkilik --reset



References

  1. How to Lock User Accounts After Failed Login Attempts
  2. Use Pam_Tally2 to Lock and Unlock SSH Failed Login Attempts
  3. Linux ETC - Login 실패시 계정 잠그기 및 PAM 설정



[컴][웹][자바][스프링] 간단한 hello world with spring 5

maven 으로 spring 5.0-mvc 의 helloworld 만들기

간단한 hello world with spring 5

  1. mvn archetype:generate -DarchetypeGroupId=fr.uha.ensisa.ff -DarchetypeArtifactId=spring-mvc-archetype -DarchetypeVersion=1.0.3 -DgroupId=com.mysimple -DartifactId=my-simple-spring -Dversion=0.8 -DarchetypeRepository=http://kolorobot.github.io/spring-mvc-quickstart-archetype

  2. pom.xml 의 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 추가
  3. plugin versrion 추가
    <build>
        ...
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                ...
            </plugin>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.0</version>
                ...
            </plugin>
        </plugins>
    </build>
    

maven 에서 local jar import 하기

<repository>
    <id>in-project</id>
    <name>In Project Repo</name>
    <url>file://${project.basedir}/libs</url>
</repository>

<dependency>
    <groupId>dropbox</groupId>
    <artifactId>dropbox-sdk</artifactId>
    <version>1.3.1</version>
</dependency>

libs 안의 구조는 아래처럼 만든다.
/groupId/artifactId/version/artifactId-verion.jar


원하는 곳에 local repository 를 만들어서 사용하는 법

개인적으로 이방법이 가장 나은듯 하다.
  • Randomized Sort: Configuring Maven to Use a Local Library Folder
    • mvn install:install-file -Dfile=c:\\a\\programming\\java\\simple-spring\\my-simple-spring\\lib\\exafe-common-1.0.1.jar  -DgroupId=com.nh -DartifactId=nh-api -Dversion=1.0.1 -Dpackaging=jar -DlocalRepositoryPath=c:\\a\\programming\\java\\simple-spring\\my-simple-spring\\lib 
      
    • 이런식으로 등록하고, pom.xml 에 <dependency> 를 추가하면 된다.
maven-war-plugin 사용시
참고로 'maven-war-plugin' 을 사용하게 되면, <distributionManagement> 에 repository 를 추가해줘야 한다.
<repositories>
    ...
    <repository>
        <!-- DO NOT set id to "local" because it is reserved by Maven -->
        <id>lib</id>
        <url>file://${project.basedir}/lib</url>
    </repository>
</repositories>
<distributionManagement>
    <repository>
        <!-- DO NOT set id to "local" because it is reserved by Maven -->
        <id>lib</id>
        <url>file://${project.basedir}/lib</url>
    </repository>
</distributionManagement>

local repository 에 jar 을 등록

.so 등 다른 type 의 library 를 이용할 때

특정 file 을 war 에 포함하기

.dll 같은 특정파일을 target/WEB-INF/lib 에 넣고 싶었다. 이 .dll 을 lib/*.jar 에 의해 쓰이는 파일이다. 그래서 찾은 방법은 그냥 copy 해 넣는 방법이 가장 나았다. 아래를 참고하자.
<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>exec-maven-plugin</artifactId>
 <version>1.6.0</version>
 <executions>
  <execution>
   <id>copy-libs</id>
   <phase>prepare-package</phase>
   <goals>
    <goal>exec</goal>
   </goals>
  </execution>
 </executions>
 <configuration>
  <workingDirectory>${project.basedir}</workingDirectory>
  <executable>cp_sodll.bat</executable>
  <!-- <executable>bash</executable>
  <commandlineArgs>handleResultJars.sh</commandlineArgs> -->
 </configuration>
</plugin>

tomcat 띄우기

  1. tomcat download : Apache Tomcat® - Apache Tomcat 9 Software Downloads
  2. 압축을 푼다.
  3. cmd 창을 열고,
  4. <tomcat_root>\bin\catalina.bat 실행

tomcat의 debug port 열기

JPDA_ADDRESS port 로 attach를 하면 된다.
set JPDA_ADDRESS=8000
set JPDA_TRANSPORT=dt_socket
bin/catalina.bat jpda start



References

  1. Create Spring Web MVC Project from Maven Archetype in Eclipse Neon - Pega Exchange

[컴][웹] open graph meta tag

태그 / 메타태그 / 페북 메타태그 / 카카오톡 메타 태그 / 텔레그램 메타태그

open graph meta tag


meta property 중 open graph 관련 meta 를 수정할일이 생겼다. 몇가지 알게된 사실이 있어서 적어놓는다. 아래는 필자가 사용한 meta tag 이다.

<meta property="og:title" content="사이트 제목">
<meta property="og:type" content="website">
<meta property="og:description" content="이 사이트는 개인 사이트 입니다.">
<meta property="og:url" content="https://www.mysite.com:443">
<meta property="og:image" content="http://www.mysite.com/apple-touch-icon.png">
<meta property="og:image:secure_url" content="https://www.mysite.com/apple-touch-icon.png">
<meta property="og:image:width" content="180" />
<meta property="og:image:height" content="180" />


og:image 의 content 는 path 가 아니라 url 이다.[ref. 2]

처음에는 그저 path 를 적으면 되는지 알았다. 하지만 그러면 메신저등에서 제대로 동작하지 않는다.

https 를 사용할 때는 og:image:secure_url 을 사용하자.

이것은 확실치 않지만, ref. 1의 글에서도 https 는 secure_url 을 사용하라고 하기도 하고, 실제로 og:image 에 https url 을 넣고 텔레그램(telegram) 에서 테스트를 해봤는데 잘 동작하지 않았다.

og:image 의 url 을 변경하지 않으면 다시 updaet 하지 않는 경우도 있다.

이것은 적어도 facebook 에서는 맞는 이야기 같다. ref. 3 을 참고하자.

메신저의 cache 된 image 를 purge 하는 법

각 메신저마다 refresh 하는 법을 제공한다.




References

  1. The Open Graph protocol
  2. https://stackoverflow.com/a/9858694
  3. Webmasters - Sharing, Facebook developers



[컴][유틸] VSCode 에서 간단한 Maven project 사용하기

vscode java /

VSCode 에서 간단한 Maven project 사용하기


vscode 에서 Maven for Java 를 사용 해 보자.

java 관련 extension들

아래 3개의 extension 을 설치하자.


maven install

  1. 여기서는 Windows 를 이용한다.
  2. 여기 서 download 를 하자.(apache-maven-3.5.4-bin.zip) 을 다운로드 하면 된다.
  3. 그리고 원하는 경로에 압축을 풀자. 여기서는 아래 경로에 풀었다.
    1. c:\a\apps\maven\apache-maven-3.5.4
  4. Maven – Installing Apache Maven 에서 얘기하는 것처럼 Windows 에는 2가지를 해줘야 한다.
    1. %JAVA_HOME%변수 설정(시스템 > 고급 시스템 설정 >  환경변수 )
    2. %PATH%에 maven\bin 의 경로를 추가
  5. cmd 를 열어서 mvn -v 를 해서 동작하면 설정이 잘 된 것이다.

maven 으로 project 만들기

아래처럼 해주면 간단한 project 를 하나 생성할 수 있다.
mvn archetype:generate -DgroupId=com.mynamh.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false



참고: maven 의 Archetype : maven 의 Archetype은 maven template 을 자동으로 생성해주는 tool 같은 것이다. 자신만의 archetype 을 생성할 수도 있고, 기존에 만들어진 archetype 을 사용할 수도 있다.


Vs Code 에서 mvn path 설정하기

vscode 를 열자. 그리고 Open User Setting 을 하자. 그리고 아래 처럼 mvn 실행파일의 경로를 set 해주자. 아래는 Red Hat's Java Language Support extension을 설치한 상황에서 configuration 이다. (java.home)
{...
  "maven.executable.path": "c:\\a\\apps\\maven\\apache-maven-3.5.4\\bin\\mvn.cmd",
  "java.home": "c:\\Program Files\\Java\\jdk1.8.0_121", // Red Hat's Java Language Support extension 
  "maven.terminal.useJavaHome": true,
}

Vs Code 에서 project 불러오기

  • File > Open Folder > <project folder>선택

compile 하기

이제 command pallet (ctrl+shift+p) 에서 아래처럼 maven compile 을 하자.
  • Maven: Execute commands > my-app 선택 > compile

실행하기

compile 이 다 되면 F5를 눌러서 debugger 로 run 을 하면 된다.


Spring Web app (Spring Boot)

  • Build Java Web Apps with VS Code
    1. git clone https://github.com/spring-guides/gs-spring-boot.git
    2. vscode 에서 연다.
    3. complete/src/main/java/hello/Application.java 를 open
    4. F5(debugger run) 를 누르면, launch.json 이 생성된다.
    5. 다시 F5 를 누르면 실행된다.
    6. 브라우저를 열고 localhost:8080 으로 접속해 보면 화면이 보인다.

attach debugger

  • 간단한 hello world with spring 5 > tomcat의 debug port 열기 를 참고하자.
  • Tomcat for Java - Visual Studio Marketplace : 이것은 war 을 debug 하는 기능은 있지만, 윈도우10에서 제대로 동작하지 않았다. war 을 선택해도 제대로 webapp directory 에 copy 하지 못했다. 이부분만 해주면 되지만, 여러모로 그냥 .bat를 task.json에 등록해서 사용하는 것이 나은듯 하다.

[컴][웹] Scaling

스케일링 / 확장 / 웹 확장 / 서버 확장 / 서버 증설 / 디비 증설 / 디비 스케일링

Scaling

Database Scaling

https://youtu.be/dkhOZOmV7Fo



App Server Scaling

https://youtu.be/xUumgxZ04SM

[컴][리눅스] sudo group 에 계정 추가

자신의 계정의 sudo 가 되게 하는 법 / sudo가 안되는 이유 /

sudo group 에 계정 추가

자신의 계정의 sudo 가 안될때는 sudo group 에 user account 를 추가해주면 된다. 그리고 재로그인을 하자.

sudo usermod -a -G sudo <user-account>

gpasswd -a user_account group


group 에서 user 삭제

gpasswd -d user_account group


sudo 가 가능한 그룹 확인

vi /etc/sudoers

아래처럼 가능한 그룹을 확인할 수 있다.
...

%wheel  ALL=(ALL)   ALL

...


References

  1. sudo - How can I add a new user as sudoer using the command line? - Ask Ubuntu
  2. How do I remove a user from a group? - Unix & Linux Stack Exchange