반응형

리눅스에 MariaDB(MySQL)를 설치하고 데이터베이스 서버에 원격으로 접속 해 보자.

 

MariaDB 서버 및 클라이언트를 설치한다.

윈도우용 MariaDB 설치 파일은 서버와 클라이언트를 함께 설치 하지만 리눅스(우분투)용 MariaDB는 따로 설치해야 한다.

 

설치가 완료 되었다면 클라이언트를 실행해 본다.

 

클라이언트 실행에 문제가 없다면 설정파일을 열어준다.

MariaDB는 기본적으로 원격 접속이 막혀있다. 설정을 변경하기 위해 아래 경로의 파일을 수정해야 한다.

/etc/mysql/mariadb.conf.d/50-server.cnf

 

'bind-address = 127.0.0.1' 을 주석처리 하고 저장한다.

※ 방화벽이 설정되어 있다면 MariaDB가 사용하는 포트를 열어준다.

sudo ufw allow 3306

 

 

MariaDB(MySQL) 사용 포트 확인.

show global variables like 'port';

 

서버에 접속할 클라이언트가 사용하는 IP 주소를 확인한다.

데이터베이스 서버에 접속할 클라이언트의 IP 주소를 미리 서버에 등록해야 한다.

서버를 WMware 에 설치했기 때문에 IP 주소는 192.168.0.16 이 아니라 192.168.171.1 을 사용한다.

 

서버가 설치된 컴퓨터에서 사용자 정보가 들어 있는 mysql.user 테이블을 확인해 본다.

로컬호스트의 root 사용자(리눅스의 root 사용자와 무관)만 등록되어 있다. 로컬호스트 이므로 원격으로 접속할 수 없다.

 

모든 데이터베이스에 모든 권한을 가지고 192.168.171.XXX에서 접속하는 sean이라는 사용자를 만든다. password는 1234.

유동 IP의 경우 재부팅 할 때마다 IP가 바뀔 수 있으므로 192.168.171.XXX 범위의 IP 주소를 가지는 컴퓨터는 모두 접속 할 수 있도록 설정 한다.

grant all on *.* to sean@'192.168.171.%' identified by '1234';

 

 

원격 사용자 설정 후, MariaDB를 재시작하고 데이터베이스 서버가 설치된 컴퓨터의 IP 주소(192.168.171.200)를 확인한다.

sudo systemctl restart mariadb

 

클라이언트에서 서버로 접속한다.

MariaDB(MySQL) 클라이언트를 실행하고 아래와 같이 입력한다.

mysql -h (IP 주소) -u (사용자) -p

 

-p 옵션에 password를 바로 입력해도 된다.

-p 옵션에 password는 공백 없이 붙여야 한다.

-p 1234 (X)

-p1234 (O)

 

반응형
Posted by J-sean
:
반응형

2019.10.08 - [Linux] - Build your own web server with Fedora linux - 페도라 리눅스로 간단한 웹서버 만들기

2021.08.25 - [Linux] - Linux(Ubuntu) Static IP Configuration - 리눅스(우분투) 고정 IP

 

리눅스(우분투)로 간단한 웹서버를 만들어 보자.

 

패키지 리스트를 업데이트 한다.

 

패키지를 업데이트 한다.

 

apache2를 설치 한다.

 

active 상태인지 확인 한다.

 

■ systemctl 명령어
- start: 서비스 시작
- stop: 서비스 중지
- status: 서비스 상태 확인
- restart: 서비스 재시작
- reload: 서비스를 중지하지 않고 설정값을 반영
- enable: 시스템 재부팅시 자동으로 서비스 실행
- disable: enable 해제

 

서버에 접속하기 위해 IP 주소를 확인 한다.

 

 

다른 컴퓨터로 접속했을때 위와 같은 Default Page가 나오면 정상이다.

 

Default Page를 수정해 보자.

 

Default Page의 HTML 코드. 모두 삭제 한다.

 

위와 같은 코드를 입력한다.

 

다시 서버에 접속해 보면 직접 입력한 내용이 출력 된다.

 

 

PHP를 설치 한다.

 

PHP 코드를 입력하기 위한 파일을 만든다.

 

PHP 정보를 표시하는 간단한 코드를 입력 한다.

 

IP 주소/PHP 파일(http://192.168.171.128/index.php) 로 접속하면 PHP 정보를 표시하는 화면이 표시된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투) 서버 IP를 고정해 보자.

 

현재 IP 주소는 192.168.171.128 이다.

 

DNS Server IP 주소는 192.168.171.2 다.

※ 참고

Ubuntu 24.04에서 systemd-resolve는 resolvectl로 이름이 바뀌었다. resolvectl을 실행하면 DNS Server 주소가 표시된다.

 

Gateway IP 주소는 192.168.171.2 다.

 

/etc/netplan/00-installer-config.yaml 파일을 열어준다.

 

 

00-installer-config.yaml 의 초기 설정.

 

원하는 IP 주소(192.168.171.200)와 위에서 찾은 IP 정보를 이용해 수정한다.

 

netplan apply를 실행하면 재부팅 하지 않아도 된다.

 

IP가 고정되었다.

 

※ 참고

Ubuntu 24.04 이후는 아래 링크를 참고하자.

Ubuntu Manuals

Setting a static IP address in Ubuntu 24.04 using netplan

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 OpenCV 이미지(cv::Mat)를 Qt로(QImage::QImage) 디스플레이 해 보자.

(cv::Mat ↔  QImage::QImage)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <opencv2/opencv.hpp>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
    ~Picture();
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass to receive paint events passed in event.
    void drawPicture(QPainter* qp);
    QImage Mat2QImage(cv::Mat const& src);
    cv::Mat QImage2Mat(QImage const& src);
 
private:
    int height;
    int width;
    QImage qtImage;
    cv::Mat cvImage;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    //image.load("Barbara Palvin.png");
    //cvimage = QImage2Mat(image);
 
    //Read images from OpenCV. Not from Qt.
    cvImage = cv::imread("Barbara Palvin.png", cv::IMREAD_COLOR);
    if (cvImage.empty())
    {
        std::cerr << "Image load failed." << std::endl;
 
        exit(EXIT_FAILURE);
    }
 
    cv::Mat tempCvImage;
    cv::cvtColor(cvImage, tempCvImage, cv::COLOR_RGB2GRAY);
 
    qtImage = Mat2QImage(tempCvImage);
    tempCvImage = QImage2Mat(qtImage);
 
    cv::resize(tempCvImage, tempCvImage, cv::Size(), 1.51.5);
    cv::imshow("OpenCV", tempCvImage);
 
    height = qtImage.height();
    width = qtImage.width();
 
    this->resize(width, height);
}
 
Picture::~Picture()
{
 
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the specified name is not used in the body
    // of a function. This can be used to suppress compiler warnings while allowing functions to be
    // defined with meaningful parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, qtImage);
}
 
QImage Picture::Mat2QImage(cv::Mat const& src)
{
    cv::Mat temp;
    cv::cvtColor(src, temp, cv::COLOR_BGR2RGB);
    QImage dest((const uchar*)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    dest.bits();
    // Enforce deep copy
    // See documentation of QImage::QImage (const uchar * data, int width, int height, Format format)
 
    return dest;
}
 
cv::Mat Picture::QImage2Mat(QImage const& src)
{
    cv::Mat temp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
    cv::Mat result; // Deep copy
    cv::cvtColor(temp, result, cv::COLOR_BGR2RGB);
 
    return result;
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Qt");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

 

소스를 입력한다. (qtcv.cpp)

 

컴파일(빌드)하고 실행하면 cv::imshow(), QPainter::drawImage() 모두 잘 표시된다. (OpenCV는 50% 확대)

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 이미지를 디스플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <QApplication>
#include <QWidget>
#include <QPainter>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass
    // to receive paint events passed in event.
    void drawPicture(QPainter* qp);
 
private:
    int height;
    int width;
    QImage image;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    image.load("Barbara Palvin.png");
    height = image.height();
    width = image.width();
 
    this->resize(width, height);
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the
    // specified name is not used in the body of a function.
    // This can be used to suppress compiler warnings while
    // allowing functions to be defined with meaningful
    // parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, image);
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Picture Example");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

소스를 입력한다. (qt.cpp)

 

컴파일(빌드)하고 실행하면 이미지가 디스플레이된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 GUI 프로그래밍을 해 보자.

 

Qt5를 설치한다.

 

단순한 window를 만드는 소스를 입력한다. (qt.cpp)

 

-fPIC 옵션과 함께 컴파일(빌드)하고 생성된 파일을 실행하면 Simple Example 윈도우가 나타난다.

 

이번엔 같은 소스를 qmake를 이용해 컴파일(빌드)해 보자. -project 옵션과 함께 실행하면 c.pro 파일이 생성된다. (디렉토리 이름.pro)

 

 

c.pro 파일의 내용을 보면 Qt Widgets 모듈이 포함되지 않았다.

 

파일의 끝에 Qt Widgets 모듈을 포함시킨다.

 

qmake, make 명령을 차례로 실행하면 컴파일(빌드)이 완료된다.

 

컴파일(빌드)된 파일을 실행하면 윈도우가 나타난다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+를 이용해 이미지를 디스플레이 해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <gtk/gtk.h>
 
static gboolean button_press_callback(GtkWidget* event_box, GdkEventButton* event, gpointer data)
{
    g_print("Event box clicked at coordinates %f,%f\n", event->x, event->y);
 
    return TRUE;
}
 
static void activate(GtkApplication* app, gpointer user_data)
{
    GtkWidget* window;
    GtkWidget* image;
    GtkWidget* event_box;
 
    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 300300);
 
    event_box = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(window), event_box);
 
    image = gtk_image_new_from_file("Barbara Palvin.jpg");
    gtk_container_add(GTK_CONTAINER(event_box), image);
 
    g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(button_press_callback), image);
 
    gtk_widget_show_all(window);
}
 
int main(int argc, char** argv)
{
    GtkApplication* app;
    int status;
 
    app = gtk_application_new("sean.s-engineer.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
 
    return status;
}
 
 
 

 

컴파일(빌드)하고 실행하면 창에 이미지가 디스플레이 된다. 클릭하면 좌표가 터미널에 표시된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+3를 이용해 GUI 프로그래밍을 해 보자.

 

GTK+3를 설치한다.

 

단순한 window를 만드는 예제 소스를 입력한다.

 

컴파일(빌드)하고 실행하면 창이 나타나다. 단순한 창이지만 이동, 종료등의 모든 기본적인 기능을 갖고 있다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <gtk/gtk.h>
 
/* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello World\n");
}
 
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    /* If you return FALSE in the "delete-event" signal handler,
     * GTK will emit the "destroy" signal. Returning TRUE means
     * you don't want the window to be destroyed.
     * This is useful for popping up 'are you sure you want to quit?'
     * type dialogs. */
 
    g_print ("delete event occurred\n");
 
    /* Change TRUE to FALSE and the main window will be destroyed with
     * a "delete-event". */
 
    return TRUE;
}
 
/* Another callback */
static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}
 
int main( int   argc,
          char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    
    /* This is called in all GTK applications. Arguments are parsed
     * from the command line and are returned to the application. */
    gtk_init (&argc, &argv);
    
    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    /* When the window is given the "delete-event" signal (this is given
     * by the window manager, usually by the "close" option, or on the
     * titlebar), we ask it to call the delete_event () function
     * as defined above. The data passed to the callback
     * function is NULL and is ignored in the callback function. */
    g_signal_connect (window, "delete-event",
              G_CALLBACK (delete_event), NULL);
    
    /* Here we connect the "destroy" event to a signal handler.  
     * This event occurs when we call gtk_widget_destroy() on the window,
     * or if we return FALSE in the "delete-event" callback. */
    g_signal_connect (window, "destroy",
              G_CALLBACK (destroy), NULL);
    
    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    
    /* Creates a new button with the label "Hello World". */
    button = gtk_button_new_with_label ("Hello World");
    
    /* When the button receives the "clicked" signal, it will call the
     * function hello() passing it NULL as its argument.  The hello()
     * function is defined above. */
    g_signal_connect (button, "clicked",
              G_CALLBACK (hello), NULL);
    
    /* This will cause the window to be destroyed by calling
     * gtk_widget_destroy(window) when "clicked".  Again, the destroy
     * signal could come from here, or the window manager. */
    g_signal_connect_swapped (button, "clicked",
                  G_CALLBACK (gtk_widget_destroy),
                              window);
    
    /* This packs the button into the window (a gtk container). */
    gtk_container_add (GTK_CONTAINER (window), button);
    
    /* The final step is to display this newly created widget. */
    gtk_widget_show (button);
    
    /* and the window */
    gtk_widget_show (window);
    
    /* All GTK applications must have a gtk_main(). Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    gtk_main ();
    
    return 0;
}
 

 

GTK+2 스타일의 예제 소스를 입력해 보자.

 

GTK+2 스타일의 소스를 빌드해도 문제 없다. Hello World 버튼을 클릭한다.

 

터미널 출력까지 잘 된다.

 

반응형
Posted by J-sean
: