Skip to content

**** ****

for my bad memories..

CentOS 6.x 버전에 repo 추가하기

2021-06-14


CentOS 6.x 버전은 공식 업데이트가 끊긴상황임.
아래와 같이 repo 를 업데이트하자.

32Bit

echo "https://vault.centos.org/6.10/os/i386/" > /var/cache/yum/i386/6/base/mirrorlist.txt
echo "http://vault.centos.org/6.10/extras/i386/" > /var/cache/yum/i386/6/extras/mirrorlist.txt
echo "http://vault.centos.org/6.10/updates/i386/" > /var/cache/yum/i386/6/updates/mirrorlist.txt

64Bit

echo "https://vault.centos.org/6.10/os/x86_64/" > /var/cache/yum/x86_64/6/base/mirrorlist.txt
echo "http://vault.centos.org/6.10/extras/x86_64/" > /var/cache/yum/x86_64/6/extras/mirrorlist.txt
echo "http://vault.centos.org/6.10/updates/x86_64/" > /var/cache/yum/x86_64/6/updates/mirrorlist.txt

CentOS 6.10 에 MySQL 5.7 설치하기

2021-06-10


5.7 버전 설치..

% rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el6-11.noarch.rpm
% yum search mysql-community
% yum install mysql-community-server mysql-community-devel

다음 데몬 시작

% service mysqld start

다음 mysql 콘솔 진입해보기

% mysql -u root -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

분명 패스워드 설정한 적이 없는데 에러가 발생 하면..
/var/log/mysqld.log 해당 파일에 임시 비번(ZC9*!kTPSM=i) 이 있음.
A temporary password is generated for root@localhost 문구를 찾을것.

2021-06-10T01:47:43.604015Z 0 [Warning] CA certificate ca.pem is self signed.
2021-06-10T01:47:44.473723Z 1 [Note] A temporary password is generated for root@localhost: ZC9*!kTPSM=i
2021-06-10T01:48:07.696819Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use

다음 root 패스워드 변경하기..
패스워드 정책이 높아서 변경이 잘 안됨.. (정책 변경후 패스워드 변경)

mysql> SET GLOBAL validate_password_policy=LOW;
mysql> use mysql;
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '패스워드';
mysql> quit;

이제 변경된 비번으로 로그인하면됨..

그리고 mysql 이 재시작 될때도 적용해야 하므로..
my.cnf 파일에도 기록한다.

validate_password_policy=LOW

그리고 5.6 버전부터 필드 생성시 공백 허용이 기본으로 안되서.. 다음와 같은 에러가발생..

Field doesn't have a default values

하여.. 호환성을 위해서.. my.cnf 파일에 다음을 기록.

sql_mode=NO_ENGINE_SUBSTITUTION

——————————————————
아래는 참고로.. mysql 완전 삭제방법..

% yum list installed | grep mysql
% yum remove -y mysql-community-*
% rm -rf /var/lib/mysql

Vector 속도 테스트

2021-03-29


이미 요소의 갯수를 알고 있을때의 속도 테스트를 해봄..
테스트 비교는
Raw Array, C로 구현된 Vector (https://github.com/goldsborough/vector), C++ FBVctor (https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md), C++ Standard Vector

#include <iostream>
#include <chrono>

#include <folly/memory/Malloc.h>
#include <folly/FBVector.h>

#include <vector>

#include <vector/vector.h>

int main(void)
{
	{
		std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

		unsigned int *vec = (unsigned int *)malloc(1000000000 * sizeof(unsigned int));

		for(unsigned int i=0; i<1000000000; i++) {
			vec[i] = i;
		}

		std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
		std::cout << "array: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

		std::cout << "Press any key to next test." << std::endl;
		getchar();
		
		free(vec);
	}

	{
		std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

		Vector vec;
		vector_setup(&vec, 1000000000, sizeof(unsigned int));

		for(unsigned int i=0; i<1000000000; i++) {
			vector_push_back(&vec, &i);
		}

		std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
		std::cout << "C Vector: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

		std::cout << "Press any key to next test." << std::endl;
		getchar();
		
		vector_clear(&vec);
		vector_destroy(&vec);
	}

	{
		std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

		folly::fbvector<unsigned int> vec;
		vec.reserve(1000000000);
		for(int i=0; i<1000000000; i++) {
			vec.push_back(i);
		}

		std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
		std::cout << "C++ FBVector: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

		std::cout << "Press any key to next test." << std::endl;
		getchar();
		
		vec.clear();
		vec.shrink_to_fit();
	}

	{
		std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

		std::vector<unsigned int> vec;
		vec.reserve(1000000000);
		for(int i=0; i<1000000000; i++) {
			vec.push_back(i);
		}

		std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
		std::cout << "C++ Vector: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

		std::cout << "Press any key to exit." << std::endl;
		getchar();

		vec.clear();
		vec.shrink_to_fit();
	}

	return 0;
}
array: Time passed (sec) : 2.27096 seconds
Press any key to next test.

C Vector: Time passed (sec) : 11.588 seconds
Press any key to next test.

C++ FBVector: Time passed (sec) : 6.22477 seconds
Press any key to next test.

C++ Vector: Time passed (sec) : 14.0583 seconds
Press any key to exit.

결과는 Raw Array 가 가장 빠름.


PHP 에서 특정 국가만 허용하기

2021-03-12


tcltk.co.kr 에서 drupal 을 사용중인데..
자꾸 스팸 글과 스팸 유저 때문에 골머리를 썩어서.. 시간좀 내서 알아봤음.

IP2Location (https://github.com/chrislim2888/IP2Location-PHP-Module)이라는 php 모듈이 있는걸 찾았고..
아래와 같이 druapl index.php 에 적용.

우선 IP2Location 폴더를 적절히 만들고 파일을 업로드하고 아래와 같이 한국 국가만 접근 가능토록 코드를 작성.

include DRUPAL_ROOT . '/IP2Location/Database.php';
include DRUPAL_ROOT . '/IP2Location/IpTools.php';
include DRUPAL_ROOT . '/IP2Location/WebService.php';

$db = new \IP2Location\Database(DRUPAL_ROOT . '/IP2Location/IP2LOCATION-LITE-DB1.BIN', \IP2Location\Database::FILE_IO);
$records = $db->lookup($_SERVER['REMOTE_ADDR'], \IP2Location\Database::ALL);

$countryCode = $records['countryCode'];
//echo $records['countryName'] . "- (".$records['countryCode'].")";

if($countryCode != 'KR') {
	echo 'You are connected from ' . $records['countryName'] . '.</br>';
	echo 'Only Korea(Republic of) country is allowed.';
	exit;
}

적용후 vpn 으로 접속하면..

흐흐.. 일단 잘됨. 이제 골머리는 썩지 않겠지?..
근데 이게 좋은 선택일까..


GNU utilities for Win32

2021-01-21


http://unxutils.sourceforge.net/

GNU 유틸리티중 유용한게 상당히 많은데..
이를 윈도우즈에서 사용할수 Win32로 포팅한 프로젝트가 GNU utilities for Win32 임.
물론 오래된 버전을 기준으로 하지만 dll 의존성 없이 딱딱 exe 하나만 있으면 사용가능하기에 아주 유용함.

먼저 아래의 파일을 받고.. usr/local/wbin 폴더내의 파일들 적당한곳에풀고
https://sourceforge.net/projects/unxutils/files/unxutils/current/UnxUtils.zip/download

다음 아래의 파일을 다운받아.. 기능개선 패치를 한다.
http://unxutils.sourceforge.net/UnxUpdates.zip

이제 사용하면된다.


Python 무설치 버전

2021-01-21


파이썬 공식 홈페이지에 무설치 버전을 제공하고 있음.
(https://www.python.org/downloads/release/python-391/)

아래로 쭉 내리다면 Windows embeddable package (64-bit) 이걸 받는다.

무설치 버전의 최고의 장점은 폴더채로 들고 다니면 어디서든 사용가능한 장점이 있음.
또 다른 응용 프로그램에 포함시켜서 파이썬의 기능을 이용할수도 있고..

어쨌든.. zip 파일을 다운받아 압축을 풀면 바로 사용가능함.
근데 문제는 pip 가 없다? pip가 없으면 외부 모듈 설치가 난감함.

pip 설치는 다음과 같이..
get-pip.py 를 아래에서 다운받아 적절한 폴더에 넣어둔다.
https://bootstrap.pypa.io/get-pip.py

다음 아래와 같이 설치한다.

C:\python-3.9.0-embed-amd64>python get-pip.py
Collecting pip
  Using cached pip-20.3.3-py2.py3-none-any.whl (1.5 MB)
Collecting setuptools
  Downloading setuptools-51.3.3-py3-none-any.whl (786 kB)
     |████████████████████████████████| 786 kB 1.6 MB/s
Collecting wheel
  Downloading wheel-0.36.2-py2.py3-none-any.whl (35 kB)
Installing collected packages: pip, setuptools, wheel
  WARNING: The scripts pip.exe, pip3.9.exe and pip3.exe are installed in 'C:\python-3.9.0-embed-amd64\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts easy_install-3.9.exe and easy_install.exe are installed in 'C:\python-3.9.0-embed-amd64\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The script wheel.exe is installed in 'C:\python-3.9.0-embed-amd64\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-20.3.3 setuptools-51.3.3 wheel-0.36.2

C:\python-3.9.0-embed-amd64>

이제 모듈을 설치할려고하니.. 이런 에러가..

C:\python-3.9.0-embed-amd64>Scripts\pip.exe install python-pptx
Traceback (most recent call last):
  File "runpy.py", line 197, in _run_module_as_main
  File "runpy.py", line 87, in _run_code
  File "C:\python-3.9.0-embed-amd64\Scripts\pip.exe\__main__.py", line 4, in <module>
ModuleNotFoundError: No module named 'pip'

파이썬 폴더에 보면 python39._pth 파일이 있는데 이 파일 마지막에 아래를 추가.

lib\site-packages

다시 설치하면

C:\python-3.9.0-embed-amd64>scripts\pip install python-pptx
Collecting python-pptx
  Downloading python-pptx-0.6.18.tar.gz (8.9 MB)
     |████████████████████████████████| 8.9 MB 6.4 MB/s
Collecting lxml>=3.1.0
  Downloading lxml-4.6.2-cp39-cp39-win_amd64.whl (3.5 MB)
     |████████████████████████████████| 3.5 MB ...
Collecting Pillow>=3.3.2
  Downloading Pillow-8.1.0-cp39-cp39-win_amd64.whl (2.2 MB)
     |████████████████████████████████| 2.2 MB ...
Collecting XlsxWriter>=0.5.7
  Downloading XlsxWriter-1.3.7-py2.py3-none-any.whl (144 kB)
     |████████████████████████████████| 144 kB ...
Building wheels for collected packages: python-pptx
  Building wheel for python-pptx (setup.py) ... done
  Created wheel for python-pptx: filename=python_pptx-0.6.18-py3-none-any.whl size=275704 sha256=968c6fae2111efebcae960370fb4ed5ceb311d0fa762f19fc82a9994aba754b6
  Stored in directory: c:\users\ihmin\appdata\local\pip\cache\wheels\94\b7\70\0c19e32b072e500447ae9a17df9389fc046973ef1df8b0c239
Successfully built python-pptx
Installing collected packages: XlsxWriter, Pillow, lxml, python-pptx
Successfully installed Pillow-8.1.0 XlsxWriter-1.3.7 lxml-4.6.2 python-pptx-0.6.18

정상 설치됨.


ffmpeg 프레임 추출 예제

2021-01-18


ffmpeg 을 이용한 비디오 파일에서 첫 다섯개의 프레임 이미지 추출 예제..

makefile

all:
	gcc ./test.c -I/c/Temp/ffmpeg_win65/include -L/c/Temp/ffmpeg_win64/lib -lavformat -lavcodec -lswscale -lavutil -lswresample -lz -lbcrypt -lole32 -lMfplat -ltiff -liconv -llzma -lws2_32 -lSecur32 -lbz2 -lstrmiids

test.c

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

#include <stdio.h>

// compatibility with newer API
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#define av_frame_alloc avcodec_alloc_frame
#define av_frame_free avcodec_free_frame
#endif

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
  FILE *pFile;
  char szFilename[32];
  int  y;
  
  // Open file
  sprintf(szFilename, "frame%d.ppm", iFrame);
  pFile=fopen(szFilename, "wb");
  if(pFile==NULL)
    return;
  
  // Write header
  fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  
  // Write pixel data
  for(y=0; y<height; y++)
    fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  
  // Close file
  fclose(pFile);
}

int main(int argc, char *argv[]) {
  // Initalizing these to NULL prevents segfaults!
  AVFormatContext   *pFormatCtx = NULL;
  int               i, videoStream;
  AVCodecContext    *pCodecCtxOrig = NULL;
  AVCodecContext    *pCodecCtx = NULL;
  AVCodec           *pCodec = NULL;
  AVFrame           *pFrame = NULL;
  AVFrame           *pFrameRGB = NULL;
  AVPacket          packet;
  int               frameFinished;
  int               numBytes;
  uint8_t           *buffer = NULL;
  struct SwsContext *sws_ctx = NULL;

  if(argc < 2) {
    printf("Please provide a movie file\n");
    return -1;
  }
  // Register all formats and codecs
  av_register_all();
  
  // Open video file
  if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
    return -1; // Couldn't open file
  
  // Retrieve stream information
  if(avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // Couldn't find stream information
  
  // Dump information about file onto standard error
  av_dump_format(pFormatCtx, 0, argv[1], 0);
  
  // Find the first video stream
  videoStream=-1;
  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
      videoStream=i;
      break;
    }
  if(videoStream==-1)
    return -1; // Didn't find a video stream
  
  // Get a pointer to the codec context for the video stream
  pCodecCtxOrig=pFormatCtx->streams[videoStream]->codec;
  // Find the decoder for the video stream
  pCodec=avcodec_find_decoder(pCodecCtxOrig->codec_id);
  if(pCodec==NULL) {
    fprintf(stderr, "Unsupported codec!\n");
    return -1; // Codec not found
  }
  // Copy context
  pCodecCtx = avcodec_alloc_context3(pCodec);
  if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {
    fprintf(stderr, "Couldn't copy codec context");
    return -1; // Error copying codec context
  }

  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
    return -1; // Could not open codec
  
  // Allocate video frame
  pFrame=av_frame_alloc();
  
  // Allocate an AVFrame structure
  pFrameRGB=av_frame_alloc();
  if(pFrameRGB==NULL)
    return -1;

  // Determine required buffer size and allocate buffer
  numBytes=avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
            pCodecCtx->height);
  buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

  // Assign appropriate parts of buffer to image planes in pFrameRGB
  // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  // of AVPicture
  avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB24,
     pCodecCtx->width, pCodecCtx->height);
  
  // initialize SWS context for software scaling
  sws_ctx = sws_getContext(pCodecCtx->width,
         pCodecCtx->height,
         pCodecCtx->pix_fmt,
         pCodecCtx->width,
         pCodecCtx->height,
         AV_PIX_FMT_RGB24,
         SWS_BILINEAR,
         NULL,
         NULL,
         NULL
         );

  // Read frames and save first five frames to disk
  i=0;
  while(av_read_frame(pFormatCtx, &packet)>=0) {
	  // Is this a packet from the video stream?
	  if(packet.stream_index==videoStream) {
		  // Decode video frame
		  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
		  // Did we get a video frame?
		  if(frameFinished) {
			  //avcodec_align_dimensions2 (pCodecCtx, &pCodecCtx->width, &pCodecCtx->height, pFrameRGB->linesize);

			  // Convert the image from its native format to RGB
			  sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,
					  pFrame->linesize, 0, pCodecCtx->height,
					  pFrameRGB->data, pFrameRGB->linesize);

			  // Save the frame to disk
			  if(++i<=5)
				  SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
		  }
	  }

	  // Free the packet that was allocated by av_read_frame
	  av_free_packet(&packet);
  }
  
  // Free the RGB image
  av_free(buffer);
  av_frame_free(&pFrameRGB);
  
  // Free the YUV frame
  av_frame_free(&pFrame);
  
  // Close the codecs
  avcodec_close(pCodecCtx);
  avcodec_close(pCodecCtxOrig);

  // Close the video file
  avformat_close_input(&pFormatCtx);
  
  return 0;
}

FBVector

2021-01-05


페이스북에서 공개한 FBVector..
(https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md)
FBVector는 folly의 일부분으로 std::vector 를 대체하기위한 용도.
(folly는 C++의 std나 boost 라이브러리의 일부분을 개선하거나 대체 용도로 개발된 클래스 모음.)

일단 테스트해보니.. 속도면에서 상당한 개선이..

{
	std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

	folly::fbvector<unsigned int> vec;
	for(int i=0; i<1000000000; i++) {
		vec.push_back(i);
	}

	std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
	std::cout << "FBVector: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

	std::cout << "Press any key to next test." << std::endl;
	getchar();
	
	vec.clear();
	vec.shrink_to_fit();
}

{
	std::chrono::system_clock::time_point start = std::chrono::system_clock::now();

	std::vector<unsigned int> vec;
	for(int i=0; i<1000000000; i++) {
		vec.push_back(i);
	}

	std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
	std::cout << "Vector: Time passed (sec) : " << sec.count() << " seconds" << std::endl;

	std::cout << "Press any key to exit." << std::endl;
	getchar();

	vec.clear();
	vec.shrink_to_fit();
}

실행..

FBVector: Time passed (sec) : 9.05379 seconds
Press any key to next test.

Vector: Time passed (sec) : 16.3373 seconds
Press any key to exit.