기본 콘텐츠로 건너뛰기

라벨이 UNIX인 게시물 표시

Linux에서 find결과를 시간 순서대로 정렬하기

때때로 어떤 디렉토리 내용을 수정시간 순서(보통 역순)대로 정렬할 필요가 있다. 그럴 때 사용할 수 있는 옵션이 -printf 옵션이다. %T+는 마지막 수정시간을 YYYY-MM-DD+HH:MM:SS.ssssssssss 형태로 출력한다. 참조: https://man7.org/linux/man-pages/man1/find.1.html find /path/something/ -mindepth 1 -maxdepth 1 -type d \ -name 'myapp-*' -printf "%T+\t%p\n" | \ sort -r | awk -F'\t' '{print $2}'

Date in Bash

날짜/시간을 Bash에서 쓸 때, 사용한 date 유틸리티 정리 POSIX 파싱 $ date -jf '%Y%m%d' '20220714' 출력 $ date -jf '%Y%m%d' '20220714' '+%Y%m%d' 계산 # 불가능 GNU extension 파싱 $ date '+%Y%m%d' -d '20220714' 계산 $ date '+%Y%m%d' -d '20220714 +1day'

Sed 특정 문자열 포함 줄 제외하기

작업을 하다보면 sed를 많이 쓰는데, 특정 문자열을 포함하고 있으면 해당 줄을 넘기고 싶을 때가 있다. 넘기고자 하는 패턴에 명령어를 "n"을 붙이면 넘어간다. #!/bin/sed -Ef /\s?ldap\s?/n s/^(passwd:.*)/\1 ldap/g s/^(group:.*)/\1 ldap/g s/^(shadow:.*)/\1 ldap/g 참조:  https://www.gnu.org/software/sed/manual/sed.html

ftok

IPC ... Inter Process Communication. 뭐 말 그대로 프로세스끼리 말하는 통신하는 방식이다. IPC에는 여러가지 방식이 있겠지만, 일반적으로 메시지큐, 공유메모리, 세마포어 이 세가지를 읊곤 한다. (소켓도 IPC라고!) 내 머릿속에서 이러한 세가지 단어를 엎고 있는 단어가 있었으니 이름하야 'SysV'. 전화회사(AT&T)에서 1983년에 하드웨어 팔아먹으려고(스위치 용도일까?) 만든 OS가 있었으니, 이름하여 'System 5(SysV)'. 이게 큰 히트를 치면서 현대 UNIX 구조의 기초를 만들게 되었다. 이때 첫 버전인 'System 5 Release 1(SVR1)에서 이미 위에서 언급한 IPC I/F를 가지고 있었다. 참조:  http://en.wikipedia.org/wiki/System_V 오늘 알아볼(것도 없는) ftok 함수는 위에서 언급한 SysV의 IPC I/F에서 사용하는 key_t을 만들기 위한 것이다. 일단 IPC객체를 하나 얻어오려면 커널이 알아볼 수 있는 키가 필요하다. (리눅스에서 내놔야 int형이지만...) 이 키를 만드려면 ftok함수를 써서 만들어야하며, 인자는 파일패스와 8bit 프로젝트값이다. 이 두가지 인자로 커널이 알아볼 수 있는 키가 만들어지고, 이것을 통해 IPC객체를 커널에 등록하고, 프로세스와 연결할 수 있는 것이다. 사실 과거에서 지금까지 많이 쓰이는 유구한 전통이 있는 함수라고 하는데, 학교 다닐 때 한 두 번 써본 것이 전부다. 그래서 실은 저 키를 만드는 과정이나, 주의 사항도 써야겠지만 귀찮아서 그냥 RTFM... SysV가 가진 IPC I/F가 잘못 만들어진 것은 아니지만, 개인 취향으로 POSIX가 새로 규정한 IPC I/F가 좀더 끌리기에 그것을 쓰고 있다. (장점 약간과 정리한 느낌을 주는 I/F 정도가 이유라면 이유랄까...) 다음에는 POSIX에서 규정한 IPC I/F를 소개할까 한다. (다만 국내외 문서에서 POSIX I...

Message Queue of UN*X

발로 짠 UN*X message queue 프로그래밍. 아... 귀찮스러... CMake가 깔려 있다면, 아래와 같이 입력하면 대략 안성 맞춤이다. $ cmake . $ make msgprj.zip 원본 위치: http://purewell.egloos.com/3506312

TLS - Thread Local Storage

쓰레드를 돌리다보면 해당 쓰레드에서만 유효한 변수를 만들고 싶을 때가 있다. 그럴 때 어떻게 해야할까? 쓰레드 개수만큼 벡터를 잡고, 해당 쓰레드마다 벡터 인덱스를 넘겨주는 것도 나름 방법이지만, 이러한 경우를 위해 TLS라는 것이 존재한다. 축약처럼 쓰레드 안에서만 따로 스토리지를 할당한 것인데, 일반 프로세스의 스텍과 비슷하나 그 크기는 프로세스 것보다 당연히 작고 제약이 심한 편이다. 뭐 암튼 그런게 있다고 치자. * GCC 메뉴얼 보면 TLS가 아니라 TSD(Thread Storage Duration)이라고 표현하였는데 대충 같은 말이다. 이것을 위해 POSIX는 pthread_key_create, pthread_get/setspecific 등 함수를 마련해놨지만 눈만 팽글팽글 돌고, 소스만 지저분해져 보일 것 같다. 귀찮으면 C99, C++98 표준 __thread 키워드를 사용하자. MSDN에 보니 __thread가 없어 보인다. 이가 없으면 잇몸으로라도... #define __thread __declspec( thread ) 대충 이 정도면 될 듯하다. 자자 각설하고, __thread란 키워드는 TLS에 변수를 선언해주는 일을 한다. 위에 나열한 pthread_* 함수를 호출하는 것으로 컴파일러가 대신 해석해주는 것일 수도 있으나 이건 가정이므로 넘어가고. 사용에 주의해야할 점은 아래와 같다. (대충대충 표준하고 MSDN 보면서 정리한 것임) 글로벌 변수나 static 변수에만 사용 가능하다. - function 안에 local 변수가 static이 아니라면 뭐더게 TLS에 저장할까? 당연히 그럴 필요가 없기 때문에 저런 제약이 있는 것이다. 이는 class에서 멤버 변수에도 적용한 법칙이다. static으로 선언한 멤버 변수에만 저 키워드를 사용할 수 있다. SO(DLL)과 로컬 영역을 넘나들면 뻑난다. - ... 그러니까 쓰지마라. 왜? 타입에 대한 한정자로 사용이 불가능하다. - const처럼 쓰지 말라는 것이고, 무...

POSIX's thread tips

쓰레드 자신에 대한 핸들을 알고 싶다면, pthread_self라는 전역 변수를 사용할 것. 두 쓰레드 핸들을 비교하고 싶다면 pthread_equal(핸들1,핸들2)을 사용한다. 둘이 같으면 0이 아닌 값이 나온다. 쓰레드 Concurrency를 확인/설정하고 싶으면 pthread_get/setconcurrency를 사용할 것. CPU점유를 다른 쓰레드에게 양보하고 싶으면 pthread_yeild가 있다. Mutex Lock을 부모 자식 프로세스 간에 공유하고 싶다면 속성에 pthread_mutexattr_get/setpshared을 이용하여 PTHREAD_PROCESS_SHARED을 세팅한다. 컨디션 변수에도 비슷한 것이 있다. 원본 위치: http://purewell.egloos.com/3398251

POSIX thread's condition

이런 상황을 생각해보자. 쓰레드가 있고, 그것은 평상시에 자는 상태(CPU점유율 0%)이다. 그런데 문득 할 일이 생겨서 침 흘리며 자고 있는 쓰레드를 두들겨 깨우고 싶다. 어떻게 하면 좋을까? volatile bool gWakeUp(false); void* _thr(void*) {     while (!gWakeUp) usleep(1000*1000);     // something... } int main(int,char**) {     // ... init thread.     gWakeUp = true;     return 0; } 이러면 쓰것나? 뭔가 찜찜허다. gWakeUp이 true로 바뀌더라도 _thr는 최악의 경우 1초 뒤에 반응을 보일 것이다. 아힝~* 싫어~* 그래서 나온 녀석이 Condition이다. 술 먹기 전에 한 번 먹고, 먹은 다음 날 한 번 먹는다는 그것!...은 아니다. #include <cstdarg> #include <pthread.h> #include <iostream> using namespace std; pthread_cond_t cond; pthread_mutex_t mtx; pthread_attr_t attr; // Just for console. pthread_mutex_t console_lock; void display(const char* fmt, ...) {     pthread_mutex_lock(&console_lock);     va_list lst;     va_start(lst, fmt);     vfprintf(stderr, fmt, lst);     va_end(lst);   ...

공유객체 속도

UNIX 공유객체(shared object) 만들기 테스트 환경을 만들기 전에 파일명을 소개하겠다. Makefile - 빌드를 위한 스크립트 plgn.cpp - plgn.so를 위한 소스. func2 함수가 포함되어 있다. sotest.cpp - 시간 측정을 위한 소스. func1 함수가 포함되어 있다. 일단 Makefile TARGET=sotest plgn.so CXXFLAGS=-g -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT LDFLAGS=-ldl all:$(TARGET) clean:     $(RM) $(TARGET) *.o sotest:sotest.cpp plgn.so:plgn.o     $(CXX) $(CXXFLAGS) -shared -lc -o $@ $< plgn.o:plgn.cpp     $(CXX) $(CXXFLAGS) -c -fPIC $< 뭐, 대충 흉내만 내놓고... 다음은 plgn.cpp extern "C" void func2(volatile int*); void func2(volatile int* v) {     ++(*v); } 역시나 흉내내기. extern "C"를 붙여 맹글링 회피 능력을 +3 했다. (뻘소리) 다음은 sotest.cpp #include <iostream> #include <dlfcn.h> #include <sys/time.h> using namespace std; static const size_t testcount(1000000UL); long long getTimestamp(void) {     static struct timeval tv;     gettimeofday(&tv, NULL);     return 1000...

clientmqueue에서 벗어나세요.

뭐, 다르게 생각하는 사람도 있겠지만, 관리하는 서버에서 sendmail을 사용하지 않는다면 clientmqueue에 쌓이는 무지막지한 파일로부터 벗어나고 싶을 것이다. 일단 clientmqueue는 선무당 이 알아본 바로는 sendmail에서 배송지경로를 확정하지 못한 메일을 잠시 보관해두는 곳이고, 확정 지으면 mqueue로 메일을 옮긴 뒤, 배송한다고 한다. sendmail을 전혀 쓰지 않는 시스템에서 가끔씩 logwatch가 시스템에 주요로그를 간추린 보고서나 cron이 돌면서 발생하는 각종 메시지를 root로 보내주도록 설정해놓고 있다. 기특한 것들... 하지만... 역시나 귀찮다... 싶으면 /etc/crontab 을 root권한으로 열어서 가볍게 MAILTO=root를 MAILTO=""으로 바꿔 버리자. 최소한 cron으로 발생하는 메시지는 모두 무시될 것이라고 위대하신 man 5 crontab님께서 알려주셨다. (그렇지... 이 세계는 RTFM... 흑!) * 엄청나게 불어버린 clientmqueue 디렉토리에 파일을 날려주고 싶다면... clientmqueue 디렉토리에 가서 이렇게 외쳐주자. $ ls | xargs rm -f * 만약 그래도 내용을 좀 알아보고 지우고 싶은 사람은 root권한으로 crontab에 find+rm으로 일정 주기마다 지워주면 대략 좋다. $ crontab -e 30 0 * * * /usr/bin/find /var/spool/clientmqueue -mtime +30 | xargs rm -f 원본 위치: http://purewell.egloos.com/3293248

UNIX 공유객체(shared object) 만들기

#include <cstdio> using namespace std; extern "C" { extern void hello(void); } void hello(void) {     printf("void hello(void);\n"); } g++ -c -fPIC hello.cpp g++ -shared -lc -o hello.so hello.o #include <dlfcn.h> void (*func)(void); int main(int,char**) {     void* handle(dlopen("./hello.so", RTLD_LAZY));     func = (void (*)(void))dlsym(handle,"hello");     func();     return 0; } g++ -o dltest dltest.cpp -ldl 원본 위치: http://purewell.egloos.com/3177776