执行 initdb 时,代码流程是从 src\bin\initdb\initdb.c 中的 main() 函数开始执行的:
- 根据用户的输入命令行获取输入的命令名(get_progname)。
- 设置系统编码为 LC_ALL,查找执行命令的绝对路径。
- 设置系统变量(pg_data等),获取系统配置文件的源文件路径( bki 等文件),并检查该路径的有效性。
- 设置中断信号处理函数
- 创建数据库目录
- 测试当前服务器系统性能
- 在 bootstrap 模式下创建模板数据库 template1
- 创建系统试图、系统表等,并初始化系统表的初始元组,复制 template1 来创建 template0 和 postgres
- 打印操作成功等相关信息,退出
初期准备和环境配置
获取程序实际名称
在 get_progname()
函数中调用 last_dir_separator()
读取用户从终端输入的 argv[0] 的最后一个 ‘/’ 的程序名称:
nodir_name = last_dir_separator(argv0);
if (nodir_name)
nodir_name++;
else
nodir_name = skip_drive(argv0);
设置环境变量
设置环境变量主要通过函数 set_pglocale_pgservice
。
- 首先设置或读取地域化信息
setlocale()
,参数 LC_ALL 代表所有,“” 代表默认本地; - 获取到 initdb 的绝对路径
find_my_exec()
,并存储在 my_exec_path 中,我的是/home/sheep/pginstall/pg15.1/bin
;
帮助和版本信息
当用户不执行初始化动作,只是查看帮助信息或者版本信息时进入如下逻辑:
if (argc > 1)
{
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
{
usage(progname);
exit(0);
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
{
puts("initdb (PostgreSQL) " PG_VERSION);
exit(0);
}
}
解析命令行选项
while ((c = getopt_long(argc, argv, "A:dD:E:gkL:nNsST:U:WX:", long_options, &option_index)) != -1)
{
switch (c)
{
case 'A':
authmethodlocal = authmethodhost = pg_strdup(optarg);
......
default:
/* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
exit(1);
}
}
如上代码,主要是获取输入的命令后的参数选项;
其中 "A:dD:E:gkL:nNsST:U:WX:"
中每个字母即代表一个命令行选项,带 :
表示该选项后面必须带参数值。
检查认证模式有效性
如下代码:
check_authmethod_unspecified(