MySQL启动报错真相however file don‘t exists. Create writable for user ‘mysql‘

背景

今天遇到一个奇怪的问题,首次启动MySQL服务时报错:


mysqld_safe error: log-error set to '/xxx/xxx/xxx/xxx/alert.log', however file don't exists. Create writable for user 'mysql'.

我在网上找到很多博客,解决方法很简单,就是去touch /xxx/xxx/xxx/xxx/alert.log,然后重启。

问题到这里就解决了,但是疑惑增加了:

  1. 为什么启动MySQL的进程的账号aaa明明有创建文件的权限,这里却报错没有权限创建文件;

  2. 解决方案也很诡异,因为我用的也是aaa账号去执行的touch /xxx/xxx/xxx/xxx/alert.log ;

  3. 我启动的时候用的aaa账号,但是为什么报错里显示 mysql没有权限呢(Create writable for user ‘mysql’. )

百思不得其解,看了很多篇文章,好像都无法解决我的疑惑,正所谓源码之下,了无秘密。

柳暗花明

我带着这些疑惑,翻到mysqld_safe.sh的源码,此时真相大白:


  if [ -f "$err_log" -o -p "$err_log" ]; then        # Log to err_log file
    log_notice "Logging to '$err_log'."
  elif [ "x$user" = "xroot" ]; then # running as root, mysqld can create log file; continue
    echo "Logging to '$err_log'." >&2
  else
    case $logdir in
      # We can't create $err_log, however mysqld can; continue
      /tmp|/var/tmp|/var/log/mysql|$DATADIR)
        echo "Logging to '$err_log'." >&2
        ;;
      # We can't create $err_log and don't know if mysqld can; error out
      *)
        log_error "error: log-error set to '$err_log', however file don't exists. Create writable for user '$user'."
        exit 1
        ;;
    esac
  fi
fi

这段代码是 MySQL 启动脚本中的一部分,主要用于确定是否能够将错误日志(err_log)写入到指定的文件中,以及在这个过程中进行相应的日志记录。

首先检查是否存在名为 $err_log 的文件或命名管道(-f “$err_log” -o -p “$err_log”)。如果存在,会记录日志提示“Logging to ‘$err_log’.”。(这就是为什么touch 日志后能解决这个问题)

如果不存在 $err_log 文件,且当前用户是 root 用户,则记录日志提示“Logging to ‘$err_log’.”。

如果既不存在 $err_log 文件,又不是 root 用户,那么会根据 $logdir(日志目录)的值进行不同处理:

如果 $logdir 的值为 /tmp、/var/tmp、/var/log/mysql 或者 $DATADIR(数据目录),表示 MySQL 具有在这些目录中创建日志文件的权限,因此会记录日志提示“Logging to ‘$err_log’.”。

如果 $logdir 的值不在上述列举的目录中,那么记录错误日志提醒,指出错误信息“error: log-error set to ‘$err_log’, however file don’t exists. Create writable for user ‘$user’.”,并退出 MySQL 的启动过程。

我们首次启动时没有这个alert.log,而我们的账号不是root,这个路径也不是/tmp等目录,所以才会走到最后一个分支里面报错。

到这里应该已经解决了大部分的疑惑,但有一些小伙伴说,命令明明是在root权限下执行的,为什么还会报错没有权限呢?比如我在一个博客上看到,引用过来:

[root@test2 my57_3307]# /usr/local/mysql57/bin/mysqld_safe  --defaults-file=/dbdata/mysql/my57_3307/my57_3307.cnf  --ledir=/usr/local/mysql57/bin
2018-08-26T14:12:45.459798Z mysqld_safe error: log-error set to '/var/log/mysqld/my57_3307.log', however file don't exists. Create writable for user 'mysql'.

于是我继续翻源码mysqld_safe.sh,这里只标注相关的源码,感兴趣的小伙伴自行去看完整源码:

# in mysqld_safe.sh

user='@MYSQLD_USER@'

--user=*) user="$val"; SET_USER=1 ;;

可以看到如果在启动命令里有–user选项的,才会按照这个user去启动,否则是用’@MYSQLD_USER@'账号,以上命令没有指定–user,那么这个账号默认是什么呢?为什么大家的报错里最后的用户都是mysql呢?

根据全局搜索,在CMakeLists.txt里面找到了答案:

# in CMakeLists.txt
SET(MYSQLD_USER "mysql")

CMake 中的 SET(MYSQLD_USER “mysql”) 命令用于设置变量 MYSQLD_USER 的值为 “mysql”。通常情况下,这种设置会被用于替换代码中的类似 @MYSQLD_USER@ 这样的占位符。在 CMake 构建过程中,这些占位符会被实际的变量值所替代。

至此真相大白了。

真相似乎很简单,但寻找真相的道路比较曲折,但了解真相后也很开心,与君分享~

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值