MySQL - Operating system error number 13 in a file operation

Last Updated on 12월 25, 2020 by 태랑(정현호)



문제 현상



MySQL 을 시작하는 과정에서 InnoDB: Operating system error number 13 in a file operation 에러 발생된 Case 입니다.



MySQL 로그 에서는 아래와 같은 주요 메세지가 확인 되었습니다.

[ERROR] InnoDB: Operating system error number 13 in a file operation.
[ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.
[ERROR] InnoDB: os_file_get_status() failed on './ibdata1'. Can't determine file permissions
[ERROR] InnoDB: Plugin initialization aborted with error Generic error
[ERROR] Plugin 'InnoDB' init function returned error.
[ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
[ERROR] Failed to initialize builtin plugins.
[ERROR] Aborting



InnoDB: Operating system error number 13 in a file operation. 에러는 파일에 Permission 관련된 에러로 보통 확인 됩니다.



그러나 mysql data 의 Permission 은 정상인 상태 였습니다.

[root]# ls -al | grep mysql
drwxr-xr-x. 2 mysql mysql      mysql


[root]# ls -al /var/lib/mysql
total 122960
drwxr-xr-x. 5 mysql mysql 4096 .
drwxr-xr-x. 69 root root 4096 ..
-rw-r-----. 1 mysql mysql 56 auto.cnf
-rw-------. 1 mysql mysql 1680 ca-key.pem
-rw-r--r--. 1 mysql mysql 1112 ca.pem
-rw-r--r--. 1 mysql mysql 1112 client-cert.pem
-rw-------. 1 mysql mysql 1676 client-key.pem
-rw-r-----. 1 mysql mysql 431 ib_buffer_pool
-rw-r-----. 1 mysql mysql 12582912 ibdata1
<중략…>






Problem tracking



먼저 서비스(systemctl) 시작 과정에서 에러가 발생 되었기 때문에 journalctl 으로 내용을 확인 하였습니다.



[root]# systemctl start mysqld
Job for mysqld.service failed because the control process exited with error code.
See "systemctl status mysqld.service" and "journalctl -xe" for details.

* 모바일 배려로 메세지는 개행 하였습니다.



[root]# systemctl stop mysqld

* 시작시 문제가 발생될 경우 계속 retry(start) 를 하는 경우가 있어 명시적으로 stop이 필요할 수 있습니다.



[root]# journalctl -xe
setroubleshoot[3498]: failed to retrieve rpm info for /var/lib/mysql/ibdata1


[참고] 처음 확인하였을 때에는 위의 메세지만 확인 되었으나 다른 시스템에서 재현을 하는 상황에서는 아래와 같이 조금더 명확한 메세지가 확인 되었습니다.


setroubleshoot[5796]: failed to retrieve rpm info for /var/lib/mysql/ibdata1
setroubleshoot[5796]: SELinux is preventing mysqld from getattr access on the file /var/lib/mysql/ibdata1. For complete SE
python[5796]: SELinux is preventing mysqld from getattr access on the file /var/lib/mysql/ibdata1.






SELinux Log 확인


그 다음 SELinux 의 audit.log 를 확인하였습니다.


최근에 CentOS 에서 작업이나 테스트 할 경우 Selinux 를 그대로 쓰는 편이라서 권한이나 소유권은 정상이지만 문제가 발생할 경우가 많아서 selinux 로그를 주로 살펴보고 있었습니다.


[root]# vi /var/log/audit/audit.log

type=AVC msg=audit(1608796184.831:292): avc: denied { getattr } for
pid=4485 comm="mysqld" path="/var/lib/mysql/ibdata1"
dev="dm-0" ino=67750315 scontext=system_u:system_r:mysqld_t:s0
tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file permissive=0
<중략..>
fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=(none) ses=4294967295 comm="mysqld"
exe="/usr/sbin/mysqld" subj=system_u:system_r:mysqld_t:s0 key=(null)



위와 같이 Selinux 로그에서 mysql 에 대한 거부된 내용을 확인 할수 있었습니다.







audit2why 로 원인 확인

[root]# audit2why < /var/log/audit/audit.log


* audit2why 는 발생된 SELinux 의 로그에서 원인과 가능하면 해결책을 제시해주는 도구 입니다.


type=AVC msg=audit(1608796184.831:292): avc:
denied { getattr } for pid=4485 comm="mysqld" path="/var/lib/mysql/ibdata1"
dev="dm-0" ino=67750315 scontext=system_u:system_r:mysqld_t:s0
tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file permissive=0

Was caused by: Missing type enforcement (TE) allow rule.

You can use audit2allow to generate a loadable module to allow this access.



원인으로 "Missing type enforcement (TE) allow rule" 확인되며 Policy 누락에 관련된 내용정도로 확인 됩니다.







Action Plan



SELinux 의 에서 차단된 내역이 확인 되었기 때문에 해결 방법으로는 2가지가 있을 것 같습니다.

- SELinux 를 Disable 하거나

- 필요한 권한을 부여



Selinux 를 그대로 유지한 상태에서 권한을 부여 하는 편으로 진행하였습니다.


audit2allow 는 발생된 selinux 의 에러를 통해서 프로세스가 필요한 권한에 대한 정책에 대한 권한 부여 명령어를 생성해주는 도구 입니다.




[root]# audit2allow -a


수행을 하게 되면 발생된 selinux 로그를 참조하여 아래와 같이 fix 에 대한 내용을 가이드 해주게 됩니다.

#============= mysqld_t ==============
#!!!! WARNING: 'var_lib_t' is a base type.
#!!!! The file '/var/lib/mysql/ibdata1' is mislabeled on your system.
#!!!! Fix with $ restorecon -R -v /var/lib/mysql/ibdata1 <== fix 명령어
allow mysqld_t var_lib_t:file getattr;




위에서 나온 가이드 와 같이 권한을 부여 합니다.


[root]# restorecon -R -v /var/lib/mysql






그 후 mysql을 재시작하면서 추가적인 오류가 있는지를 확인 합니다.

[root]# systemctl start mysqld







conclusion



문제가 발생된 원인을 더 자세하게 확인해보면 


SELinux 사용환경에서 /var/www/html 나 /var/lib/mysql 과 같이 알려진 디렉토리에는 초기에 권한이 부여된 상태임으로 문제가 발생될 소지가 적습니다.



이번 Case 의 경우 DB를 새로 생성하여 데이터를 import 가 필요한 상황에서

1. 기존에 사용중이던  /var/lib/mysql 디렉토리를 rename 으로 백업 처리

2. 디렉토리 신규 생성 및 권한 부여
[root]# mkdir mysql
[root]# chown -R mysql:mysql mysql


이 과정에서 새롭게 만들어진 mysql 디렉토리에 selinux의 권한 속성이 없어서 발생된 case 였습니다.


패키지로 설치 후 디렉토리 권한은 아래와 같이 사용이 가능한 상태 입니다.
[root]# ls -alZ | grep mysql
drwxr-x--x. mysql mysql system_u:object_r:mysqld_db_t:s0 mysql





관련 된 다른 포스팅

답글 남기기