삽질하는플머

Ubuntu + MySQL 에서 셸 커맨드 사용

탐구생활/WEB 관련

우분투 16.04 + MySQL 에서 특정 데이터가 입력될 경우 셸 커맨드를 돌려야 할 상황이 생겼다. 
오늘 요리재료는 이럴 때 안성마춤인 lib_mysqludf_sys 되시겠다. 


깃허브 링크: https://github.com/mysqludf/lib_mysqludf_sys 


먼저 MySQL 에서 플러그인 경로를 확인하자. 


mysql> show variables like 'plugin_dir';


+---------------+------------------------+

| Variable_name | Value                  |

+---------------+------------------------+

| plugin_dir    | /usr/lib/mysql/plugin/ |

+---------------+------------------------+




UDF 소스를 내려받고.  


$ git clone https://github.com/mysqludf/lib_mysqludf_sys.git

$ cd lib_mysqludf_sys/



포함된 Makefile 을 참조해 빌드 테스트. -fPIC을 주라는 에러가 나오니 그대로 따른다. 

$ sudo apt-get install libmysqlclient-dev
$ gcc -Wall -I/usr/include/mysql -I. -fPIC  -shared lib_mysqludf_sys.c -o lib_mysqludf_sys.so


빌드 확인한 뒤, Makefile 수정. 

Makefile 

LIBDIR=/usr/lib/mysql/plugin

install:
        gcc -Wall -I/usr/include/mysql -I. -fPIC -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so



빌드 및 설치


$ sudo ./install.sh



MySQL 실행 후 테스트. 


mysql> select sys_exec('touch /tmp/test_mysql') ;

+-----------------------------------+

| sys_exec('touch /tmp/test_mysql') |

+-----------------------------------+

|                             32512 |

+-----------------------------------+

1 row in set (0.01 sec)



내부적으로 sys() 함수를 사용하는데 왠 31512 에러... 역시 한 번에 되는 건 하나도 없군. 


구글께 여쭈니 apparmor 에서 UDF 실행을 막는다는 신탁을 내려주심. 

https://www.cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands/



먼저 apparmor 의 상태를 확인. 


$ sudo apparmor_status


apparmor module is loaded.

16 profiles are loaded.

16 profiles are in enforce mode.

......

   /usr/sbin/mysqld

...



mysqld 를 대상에서 제거


$ sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/

$ sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld


# 상태 다시 확인

# sudo apparmor_status



apparmor 와 mysql 재구동


$ sudo /etc/init.d/mysql restart

$ sudo /etc/init.d/apparmor restart



MySQL 에서 sys_exe() 재시도


mysql> select sys_exec('touch /tmp/test_mysql');

+-----------------------------------+

| sys_exec('touch /tmp/test_mysql') |

+-----------------------------------+

|                                 0 |

+-----------------------------------+

1 row in set (0.01 sec)



/tmp 에 생성된 파일 확인. 


$ ll /tmp

total ...

drwxrwxrwt 13 root    root    4096 Aug 20 22:38 ./

drwxr-xr-x 24 root    root    4096 Jul  6 14:40 ../

-rw-r-----  1 mysql   mysql      0 Aug 20 22:38 test_mysql

......



이제 트리거에서 외부 실행파일을 마음껏 실행시킬 수 있다.



참고링크

https://github.com/mysqludf/lib_mysqludf_sys

http://bernardodamele.blogspot.com/2009/01/command-execution-with-mysql-udf.html

https://www.cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands/


Synology USBStation2 사용기 2. AMP 설치.

이런저런잡다구리/Synology-nas

아래 글을 먼저 읽고 오세요~ ^^;

"Synology USBStation2 사용기 1. 전원 꽂고 optware 깔기."



짤방은 재활용 쓰레기장에서 득템한 외장케이스. 앞부분 래치가 부러져 하드를 고정할 수 없어 버려진 듯. 

하우징 쇠 부분에 드릴로 구멍을 뚫고 클립을 펼쳐 관통시켰더니 잘 고정된다. e-sata, usb 지원. 

함께 입양된 1TB 하드를 넣어 USBStation2 에 물려줌. 



USBStation2의 포지션은 어디까지나 NAS가 아닌 NAS Adapter 라고 하지만, 성능면에 DS110j와 별반 다르지 않은데도 웹서비스가 빠졌다는 점은 아무리 생각해도 좀 깬다. 저렴한 버팔로 NAS도 아파치와 PHP, MySQL 정도는 기본으로 들어가 있는데 말이지... 그리고 들여다 보면 알겠지만 이미 아파치의 httpd 도 두 개나 돌고 있다. 기능이 충분한데도 넣지 않는 건 순전히 정책적인 결정이라고 생각한다. 


그러나 이미 우리 손에 쥐어진 ipkg 라는 전가의 보도!! AMP도 얼마든지 올려볼 수 있다. (버전이 좀 낮기는 해도...)


일단 관련 패키지들 설치. 


# ipkg install apache php mysql sqlite openldap-libs php-apache phpmyadmin 



우분투처럼 깔면 깔린 그대로 돌아가면 좋겠지만... 아쉽게도 몇가지 손을 봐줘야 한다. 

/opt/etc/apache2/httpd.conf 파일을 편집.


먼저 구동시 에러를 내는 74라인의 mod_ext_filter.so 모듈 로딩하는 부분은 앞에 '#'을 붙여 주석처리. 


# LoadModule ext_filter_module libexec/mod_ext_filter.so



USBStation2 에서 웹 기본 포트인 80번 포트는 이미 관리페이지인 5000번으로 리다이렉션 시키는 용도로 사용중이다. 

기본 내장된 아파치가 이 작업을 하는데 어디서 띄우는지는 아직 확인하지 못했다. (귀찮아서...) 어차피 가정용 ISP에서 80포트 막아둔 곳도 많고 필요하다면 공유기에서 포워딩하면 되니까 리슨포트는 8000 그대로 둔다. DS110j와의 가격차이를 생각하면 이 정도 쯤이야 패널티라고 생각하지 뭐.  


Listen 8000



서버명은 다음과 같이 수정. 


ServerName *:8000



LoadModule 어쩌구가 잔뜩 적혀있는 119라인 근처에 다음 두 줄을 추가해준다. 

AddType application/x-httpd-php .php
LoadModule php5_module libexec/libphp5.so


<IfModule dir_module> 부분을 찾아 다음과 같이 수정해준다. (235라인 근처...)

<IfModule dir_module>
    DirectoryIndex index.html index.htm index.cgi index.php index.php3
</IfModule>


아파치 구동. 


# /opt/sbin/apachectl start



http://usbstation2:8000 에 접속해보자. It works! 라는 반가운 메시지가 나오면 일단 성공! 




웹 서비스 루트 기본값은 /opt/share/www 이다. 여기에 다음 내용을 담은 test.php 파일을 만들어주자. 


# vi /opt/share/www/test.php


<?php

phpinfo();

?>



http://usbstation2:8000/test.php 에 접속해서 다음과 같은 화면이 나오면 최종 성공!! 





여기까지 잘 되었다면 조금 전에 설치한 phpmyadmin 도 제대로 동작할 것이다.

http://usbstation2:8000/phpmyadmin/ 에 접속 테스트. 





이제 DB에 적절한 권한을 설정하고 미디어위키를 깔건 그누보드를 깔건 마음대로 가지고 놀면 된다. 


Synology NAS의 MySQL 테이블 대소문자 구분 설정

이런저런잡다구리/Synology-nas

윈도의 MySQL 에서 작성한 DB 스키마를 Synology NAS 의 MySQL로 옮겨 테스트 하자마자 쏟아지는 에러. 

CREATE TABLE 또는 CREATE DATABASE 에서 대소문자를 예쁘게 구분해봐야 저장될 때는 소문자로 저장되는게 어찌 희안하더라니... 

윈도의  MySQL 에서는 SQL문 내의 테이블과 데이터베이스에서 대소문자를 구분하지 않지만, NAS의 리눅스에서는 구분하고 있다. 

일단 SQL문을 뜯어고쳐 대소문자를 맞춰주기는 했는데... 덕분에 아무래도 유기농 코드가 잔뜩 만들어진 듯...  (벌레 벌레~)

윈도와 리눅스의 MySQL 설정이 달라서 애를 먹은 게 한두번이 아니었지만... 그래도 이건 좀 아니잖아. 

이 설정을 동일하게 맞추는 방법이 없을까 하고 뒤져보니  lower_case_table_names 를 살펴보란다. 


http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html



이 변수의 기본값이 윈도와 맥에서는 1로, 리눅스에서는 0으로 설정된다고 한다. 각 값의 의미는 다음과 같다. 


의미
0테이블과 데이터베이스 이름들은 CREATE TABLE 또는 DATABASE 문에 정의된 문자로 디스크에 저장되며 이름 비교시 대소문자를 구분한다.
1테이블과 데이터베이스 이름들은 소문자로 저장되고 이름 비교시 대소문자를 구분하지 않는다.
2테이블과 데이터베이스 이름들은 CREATE TABLE 또는 DATABASE 문에 정의된 문자로 디스크에 저장되며 이름 비교시 대소문자를 구분하지 않는다.


가성비가 떨어지는데도 불구하고 Synology NAS를 좋아하는 건, SSH 연결을 지원하기 때문이지.
부트스트랩을 통해 이런저런 도구들도 마음대로 설치할 수 있고...

http://lycons.iptime.org/tc/49


요새는 QNAP 것도 끌리는데... 어디 출장 나가는 사람 없나... 가격 차이가 이건 뭐 두배나 나니...


아무튼 SSH로 접속한 다음 my.cnf 를 찾아보자. 응? 그렇게 생긴 파일이 하나도 없네??

my*.cnf 로 검색해보니 다섯개의 파일이 튀어나온다. 


# find / -name my*.cnf

/usr/syno/mysql/share/mysql/my-huge.cnf

/usr/syno/mysql/share/mysql/my-small.cnf

/usr/syno/mysql/share/mysql/my-innodb-heavy-4G.cnf

/usr/syno/mysql/share/mysql/my-large.cnf

/usr/syno/mysql/share/mysql/my-medium.cnf



현재 사용중인 물건은 메모리 128M짜리 DS-110j



my-medium.cnf 을 설정파일로 사용하면 되겠군. 이 파일을 /ect/my.cnf 로 복사한다. 


# cp /usr/syno/mysql/share/mysql/my-medium.cnf /etc/my.cnf



my.cnf 파일을 열고 [mysqld] 항목 아래에 다음 설정을 추가. 


lower_case_table_names = 1



NAS의 mysql 데몬 재구동은 다음과 같이. 


/usr/syno/etc/rc.d/S21mysql.sh restart



제대로 설정되었는지 확인하려면 아래 SQL을 실행. 


SHOW VARIABLES LIKE  'lower_case_table_names'


Variable_nameValue
lower_case_table_names1


우분투의 경우도 요령은 동일하다. 



모노 2.10 설치. MySql 연결 테스트.

여가생활/Unity,Mono&.Net

시작은 유니티였는데... 옆길로 참 많이 새고 있다. 


굳이 이런 시도를 해보는 이유는? 모노가 WCF를 지원하고 있다는 것에 눈이 번쩍 띄었기 때문이다. 

현재 XMLRPC+PHP로 DB를 호출하고, 이 PHP를 HipHop으로 빌드해 바이너리로 서비스하는 방식을 쓰는 중인데...

닷넷으로 WCF 서비스를 만들고 델파이로 접근해 사용하도록 바꿔준다면 손도 편하고 머리속도 간단해지니까. 

게다가 C#은 디버깅도 되잖아? 디버거 없이 날코딩하는 PHP같은 인터프리터 언어는 나이가 먹을수록 부담스러워~~


기왕에 삽질할 꺼면 모노 2.8 이상을 설치해 새 바닥에서 놀자. 


우분투에 모노 2.10 설치는 트위터의 @nbridgewater 님이 작성한 스크립트를 쓰면 한방에 해결. 

중간 중간에 sudo 암호만 넣어주면 된다. 시간은 좀 오래 걸림. 


http://www.integratedwebsystems.com/2011/02/mono-2-10-install-script-for-ubuntu-fedora/


# wget --no-check-certificate https://github.com/nathanb/iws-snippets/raw/master/mono-install-scripts/ubuntu/install_mono-2.10.sh

# chmod 755 install_mono-2.10.sh

# ./install_mono-2.10.sh



위치는 /opt/mono-2.10 에 설치된다. 다음과 같이 윈도에서 #Develop 로 작성한 .Net 4.0 바이너리를 실행시킬 수 있다. 


# /opt/mono-2.10/bin/mono ./test.exe

Hello World!

#



MySql의 닷넷용 커넥터는 MySQL 에서 직접 개발 및 배포하고 있다. 라이센스는 GPL. 

http://dev.mysql.com/downloads/connector/net/


현재 버전은 6.5.4 이다. 일단 윈도용을 내려받아 설치하자. 







#Develop 에서 mysql-test 솔루션을 시작한다. 프로젝트 탐색기의 "참조" 에서 우측키를 누른 뒤 "참조 추가" 메뉴를 클릭하자. 

GAC 탭에서 "MySql.Data" 를 선택한 뒤 "확인"을 눌러준다. 




http://www.mono-project.com/MySQL 에 MySql 에 접근하는 좋은 예제가 있다. 

int형 ID와 varchar형 Name 을 필드로 가지는 테스트용 DB에 접근하는 코드를 다음과 같이 만들어주었다. 


using System;
using System.Data;
using MySql.Data.MySqlClient;

namespace mysql_test
{
    class Program
    {
        public static void Main(string[] args)
        {
            string connectionString =     
              "Server=hostname;" +
              "Database=test;" +
              "User ID=user;" +
              "Password=password;" +
              "Pooling=false";
            
            IDbConnection dbcon;
            dbcon = new MySqlConnection(connectionString);
            dbcon.Open();
            IDbCommand dbcmd = dbcon.CreateCommand();
            
            string sql =
               "SELECT ID, Name " +
               "FROM test";
            
            dbcmd.CommandText = sql;
            IDataReader reader = dbcmd.ExecuteReader();
            while(reader.Read()) {
                int ID = (int) reader["ID"];
                string Name = (string) reader["test"];
                Console.WriteLine("Data: " + ID + " " + Name);
            }
            // clean up
            reader.Close();
            reader = null;
            dbcmd.Dispose();
            dbcmd = null;
            dbcon.Close();
            dbcon = null;

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

(#Develop 에서 코드를 복사해 블로그에 붙여넣으면 하이라이팅이 그대로 살아있네~ 좋다!!)



실행시켜보면 자알~ 동작한다. 





이제 모노의 GAC에 MySql 라이브러리를 설치해보자. http://dev.mysql.com/downloads/connector/net/ 에서 ".Net & Mono" 를 선택한 뒤 "mysql-connector-net-6.5.4-noinstall.zip" 파일을 다운받아 압축을 푼다. 이 압축파일에 포함된 dll은 모두 소문자로 되어있지만 GAC에 등록하기 위해서는 실제 C#에서 참조할 때와 동일하게 대소문자를 맞춰주어야 한다는 것에 주의!


# cd mysql-connector-net-6.5.4-noinstall/

# cd v2

# cp mysql.data.dll MySql.Data.dll

# sudo /opt/mono-2.10/bin/gacutil -i MySql.Data.dll
 Installed MySql.Data.dll into the gac (/opt/mono-2.10/lib/mono/gac)


윈도에서 작성된 바이너리를 옮겨와 다음과 같이 실행시켜보자. 


/opt/mono-2.10/bin/mono ./mysql-test.exe



결과는 짜잔~




덤으로, 앞에서 작성한 CS 코드를 우분투에서 직접 빌드하려면 다음과 같이 하면 된다. 

/opt/mono-2.10/bin/mcs mysql-test.cs  -r:System.Data.dll -r:/opt/mono-2.10/lib/mono/gac/MySql.Data/6.5.4.0__c5687fc88969c44d/MySql.Data.dll


당연한 이야기지만, 이렇게 빌드한 실행파일도 윈도에서 잘 돌아간다.