在 bash 中使用 xargs parallel & psql 导出函数
Exporting function with xargs parallel & psql in bash
我正在尝试 运行 SQL 并行地针对一个或多个 psql 兼容主机,在每个主机上按顺序 SQL 运行,使用 xargs.
bash 脚本,我从另一个脚本中获取:
# Define the count of hosts (also the number of parallel processes)
export pe_fpe_hosts_line_count=$(cat $pe_fpe_hosts_file_loc | wc -l)
# Define the function that runs SQL from a file
function func_pe_exec_sql {
while read pe_sql_file; do
psql -q -t -c "\"$pe_sql_file"\"
done <$pe_fpe_sql_file_loc
}
export -f func_pe_exec_sql
# Define the xargs parallel function
function func_pe_parallel {
while read pe_hosts_file; do
echo $pe_hosts_file | xargs -d '\n' -P $pe_fpe_hosts_line_count func_pe_exec_sql
done <$pe_fpe_hosts_file_loc
}
我得到的错误:xargs: func_pe_exec_sql: No such file or directory
。这很奇怪 - 我已经导出了函数!
示例 SQL 文件:
INSERT INTO public.psql_test SELECT 1 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 2 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 3 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 4 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 5 as myint, now() as mytime;
示例SQL 主机文件:
--host=myhost1 --port=5432 --dbname=postgres --username=cooluser
--host=myhost2 --port=5432 --dbname=postgres --username=cooluser
pe_fpe_sql_file_loc
是 SQL 文件的路径,pe_fpe_hosts_file_loc
是 SQL 主机文件的路径。
SQL在单独的事务中必须始终是运行,并且SQL文件中的每一行都需要单独插入,一个接一个。 5 应该与最大的 mytime 值位于同一行。
我将它用作 ETL 框架,但函数在数据库中定义,而不是用于简单的插入:)
我认为您对 xargs
的调用不正确。您实际上并没有将行从 pe_hosts_file
传递给函数 func_pe_exec_sql
.
您需要将管道的输入传递给函数,才能做到这一点;你需要有一个占位符,xargs
中的 -I
标志提供。
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names
read from standard input. Also, unquoted blanks do not terminate input items;
instead the separator is the newline character. Implies -x and -L 1.
使用需要使用类似下面的东西。
| xargs -d '\n' -I {} -P "$pe_fpe_hosts_line_count" bash -c 'func_pe_exec_sql "{}"'
其中 {}
是管道值的占位符,我们将其传递给由 bash -c
直接生成的子 shell 函数 func_pe_exec_sql
. {}
周围的特殊双引号是为了确保 shell 在调用函数之前扩展值。
我正在尝试 运行 SQL 并行地针对一个或多个 psql 兼容主机,在每个主机上按顺序 SQL 运行,使用 xargs.
bash 脚本,我从另一个脚本中获取:
# Define the count of hosts (also the number of parallel processes)
export pe_fpe_hosts_line_count=$(cat $pe_fpe_hosts_file_loc | wc -l)
# Define the function that runs SQL from a file
function func_pe_exec_sql {
while read pe_sql_file; do
psql -q -t -c "\"$pe_sql_file"\"
done <$pe_fpe_sql_file_loc
}
export -f func_pe_exec_sql
# Define the xargs parallel function
function func_pe_parallel {
while read pe_hosts_file; do
echo $pe_hosts_file | xargs -d '\n' -P $pe_fpe_hosts_line_count func_pe_exec_sql
done <$pe_fpe_hosts_file_loc
}
我得到的错误:xargs: func_pe_exec_sql: No such file or directory
。这很奇怪 - 我已经导出了函数!
示例 SQL 文件:
INSERT INTO public.psql_test SELECT 1 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 2 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 3 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 4 as myint, now() as mytime;
INSERT INTO public.psql_test SELECT 5 as myint, now() as mytime;
示例SQL 主机文件:
--host=myhost1 --port=5432 --dbname=postgres --username=cooluser
--host=myhost2 --port=5432 --dbname=postgres --username=cooluser
pe_fpe_sql_file_loc
是 SQL 文件的路径,pe_fpe_hosts_file_loc
是 SQL 主机文件的路径。
SQL在单独的事务中必须始终是运行,并且SQL文件中的每一行都需要单独插入,一个接一个。 5 应该与最大的 mytime 值位于同一行。
我将它用作 ETL 框架,但函数在数据库中定义,而不是用于简单的插入:)
我认为您对 xargs
的调用不正确。您实际上并没有将行从 pe_hosts_file
传递给函数 func_pe_exec_sql
.
您需要将管道的输入传递给函数,才能做到这一点;你需要有一个占位符,xargs
中的 -I
标志提供。
-I replace-str
Replace occurrences of replace-str in the initial-arguments with names
read from standard input. Also, unquoted blanks do not terminate input items;
instead the separator is the newline character. Implies -x and -L 1.
使用需要使用类似下面的东西。
| xargs -d '\n' -I {} -P "$pe_fpe_hosts_line_count" bash -c 'func_pe_exec_sql "{}"'
其中 {}
是管道值的占位符,我们将其传递给由 bash -c
直接生成的子 shell 函数 func_pe_exec_sql
. {}
周围的特殊双引号是为了确保 shell 在调用函数之前扩展值。