如何正确使用 liquibase `searchPath` 选项来指示各自的资源文件夹?

2024-05-06

我正在尝试调用update的命令liquibase如下:

liquibase update --changelog-file=./persistence/src/main/resources/changelog/db.changelog-dev.xml \
                 --url="jdbc:postgresql://localhost:5432/sigma"

这导致:

[...]
Starting Liquibase at 23:44:47 (version 4.17.2 #5255 built at 2022-11-01 18:07+0000)
Liquibase Version: 4.17.2
Liquibase Community 4.17.2 by Liquibase

Unexpected error running Liquibase: The file classpath:/changelog/db.changelog-master.xml was not found in the configured search path:
    - /Users/ikaerom/Dev/sigma-backend
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/liquibase-core.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/lib
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/jaybird.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/ojdbc8.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/snakeyaml.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/snowflake-jdbc.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/picocli.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/jaxb-runtime.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/jaxb-api.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/jaxb-core.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/hsqldb.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/connector-api.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/mssql-jdbc.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/h2.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/mariadb-java-client.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/liquibase-commercial.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/commons-lang3.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/postgresql.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/sqlite-jdbc.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/opencsv.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/commons-text.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/commons-collections4.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib/jcc.jar
    - /opt/homebrew/Cellar/liquibase/4.17.2/libexec/internal/lib
More locations can be added with the 'searchPath' parameter.

The db.changelog-dev.xml本质上包括db.changelog-master.xml,然后它还引用一些 SQL 脚本。这两个 XML 文件位于同一个资源文件夹中$PROJECT_ROOT/persistence/src/main/resources/changelog。更改日志 XML 中引用的导入/包含的 SQL 文件全部位于资源文件夹的子文件夹中。

任何指定这一点的方式都可以逃避searchPath甚至--search-path参数(如中所示文档 https://docs.liquibase.com/concepts/changelogs/how-liquibase-finds-files.html)似乎失败得很厉害:

$> liquibase update --searchPath="./persistence/src/main/resources/" --changelog-file=./persistence/src/main/resources/changelog/db.changelog-dev.xml --url="jdbc:postgresql://localhost:5432/sigma"
Unexpected argument(s): --searchPath=./persistence/src/main/resources/

那么让我们尝试其他指定的语法:

$> liquibase update --search-path="./persistence/src/main/resources/" --changelog-file=./persistence/src/main/resources/changelog/db.changelog-dev.xml --url="jdbc:postgresql://localhost:5432/sigma"
Unexpected argument(s): --search-path=./persistence/src/main/resources/

如果我尝试使用LIQUIBASE_SEARCH_PATH=,我最终得到的是这样的:

[...]
Liquibase Version: 4.17.2
Liquibase Community 4.17.2 by Liquibase

Liquibase Community detected and ignored the following environment variables:
- LIQUIBASE_SEARCH_PATH
To configure Liquibase with environment variables requires a Liquibase Pro or Liquibase Labs license. Get a free trial at https://liquibase.com/trial. Options include the liquibase.licenseKey in the defaults file, adding a flag in the CLI, and more. Learn more at https://docs.liquibase.com.
[...]

我真的不想只是为了让这个功能发挥作用而购买专业版;)。

我的问题是: 如何指定搜索路径liquibase在我的 bash shell 中获取它?

我发现很难相信这行不通,因为liquibase文档非常齐全,如果您没有正确使用它,它会尝试始终为您提供正确的提示和指示。我错过了什么?

Update:我怀疑调用顺序很重要。所以update命令应该位于列表的最后。然而,到目前为止还没有运气:

$> liquibase \
          --changelog-file=./persistence/src/main/resources/changelog/db.changelog-dev.xml \
          --url="jdbc:postgresql://localhost:5432/sigma" \
          --searchpath="./persistence/src/main/resources/changelog/" \
          update
[...]
Starting Liquibase at 14:29:51 (version 4.17.2 #5255 built at 2022-11-01 18:07+0000)
Liquibase Version: 4.17.2
Liquibase Community 4.17.2 by Liquibase

Unexpected error running Liquibase: The file ./persistence/src/main/resources/changelog/db.changelog-dev.xml was not found in the configured search path:
    - /Users/ikaerom/Dev/sigma-backend/persistence/src/main/resources/changelog
More locations can be added with the 'searchPath' parameter.

For more information, please use the --log-level flag

经过深入研究后,我自己找到了解决方案liquibase源代码。

In my db.changelog-dev.xm我有一行包括db.changelog-master.xml如下。那classpath:/必须删除:

-    <include file="classpath:/changelog/db.changelog-master.xml"/>
+    <include file="changelog/db.changelog-master.xml"/>

然后,这个调用终于起作用了(注意改编的searchPath以及相对名称changelog参数设置):

    liquibase \
          --hub-mode=off \
          --headless=true \
          --url="jdbc:postgresql://localhost:5432/sigma" \
          --searchPath="./persistence/src/main/resources" \
          --changelog-file=changelog/db.changelog-dev.xml \
          update 2>&1 | grep -Ev -- "^##"

The --hub-mode=off会阻止liquibase询问您是否要连接到 liquibase hub。剩下的就是糖衣了。

唯一的问题是当liquibase从 shell CLI 调用,最终拥有变更日志/锁定表的用户是调用liquibase命令:

ikaerom@/tmp:sigma> \dt databasechangeloglock
+--------+-----------------------+-------+---------+
| Schema | Name                  | Type  | Owner   |
|--------+-----------------------+-------+---------|
| public | databasechangeloglock | table | ikaerom |
+--------+-----------------------+-------+---------+
SELECT 1
Time: 0.011s
ikaerom@/tmp:sigma> \dt databasechangeloglock
+--------+-----------------------+-------+---------+
| Schema | Name                  | Type  | Owner   |
|--------+-----------------------+-------+---------|
| public | databasechangeloglock | table | ikaerom |
+--------+-----------------------+-------+---------+
SELECT 1
Time: 0.010s

然而,当liquibase通过调用 Spring boot 应用程序进行更新,然后表所有者用户是应用程序上下文正在设置的用户(在我的例子中是 sigma):

ikaerom@/tmp:sigma> \dt databasechangeloglock
+--------+-----------------------+-------+-------+
| Schema | Name                  | Type  | Owner |
|--------+-----------------------+-------+-------|
| public | databasechangeloglock | table | sigma |
+--------+-----------------------+-------+-------+
SELECT 1
Time: 0.010s
ikaerom@/tmp:sigma> \dt databasechangelog
+--------+-------------------+-------+-------+
| Schema | Name              | Type  | Owner |
|--------+-------------------+-------+-------|
| public | databasechangelog | table | sigma |
+--------+-------------------+-------+-------+
SELECT 1
Time: 0.009s

如果你运行你的,这会发生冲突liquibase先更新:

Caused by: liquibase.exception.DatabaseException: ERROR: relation "databasechangeloglock" already exists [Failed SQL: (0) CREATE TABLE public.databasechangeloglock (ID INTEGER NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP WITHOUT TIME ZONE, LOCKEDBY VARCHAR(255), CONSTRAINT databasechangeloglock_pkey PRIMARY KEY (ID))]
    at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:397)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:83)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:151)
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:135)
    at liquibase.lockservice.StandardLockService.init(StandardLockService.java:115)
    at liquibase.lockservice.StandardLockService.acquireLock(StandardLockService.java:286)
    ... 94 common frames omitted
Caused by: org.postgresql.util.PSQLException: ERROR: relation "databasechangeloglock" already exists
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:329)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:315)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:291)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:286)
    at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94)
    at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
    at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:393)

这同样可以通过对西格玛进行适当的授予或将所有者重新分配给合法用户来解决。或者简单地添加--username属性到 Spring Boot 应用程序上下文或数据库用户所有者的名称:

    liquibase \
          --hub-mode=off \
          --headless=true \
          --username="sigma" \
          --url="jdbc:postgresql://localhost:5432/sigma" \
          --searchPath="./persistence/src/main/resources" \
          --changelog-file=changelog/db.changelog-dev.xml \
          update 2>&1 | grep -Ev -- "^##"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确使用 liquibase `searchPath` 选项来指示各自的资源文件夹? 的相关文章

  • 为什么 $((true == false)) 在 bash 中计算结果为 1?

    为什么 bash 有以下行为 echo true false 1 我本以为这会打印0 但它打印1 以下事实使情况变得更加复杂 gt echo true 0 gt echo false 0 gt echo true true 1 gt ech
  • 当 grep "\\" XXFile 我得到“尾随反斜杠”

    现在我想查找是否有包含 字符的行 我试过grep XXFile但它暗示 尾随反斜杠 但当我尝试时grep XXFile没关系 谁能解释一下为什么第一个案例无法运行 谢谢 区别在于 shell 处理反斜杠的方式 当你写的时候 在双引号中 sh
  • Linux - 从第二个选项卡获取文本

    假设我们有这样的文件 一些文本11 一些文本12 一些文本13 一些文本21 一些文本22 一些文本23 文本由制表符分隔 我们知道第 1 列中的一些文本 但希望从第 2 列中获取文本 我知道我可以通过以下方式获取线路 grep somet
  • sh / Bash shell 脚本中 !# (bang-pound) 的含义是什么?

    我想了解这个 Scala 脚本是如何工作的 usr bin env bash exec scala 0 object HelloWorld def main args Array String println Hello world arg
  • Bash 正则表达式——似乎无法匹配任何 \s \S \d \D \w \W 等

    我有一个脚本试图从 gparted 获取信息块 我的数据如下所示 Disk dev sda 42 9GB Sector size logical physical 512B 512B Partition Table msdos Number
  • Spyder 无法启动:spyder:找不到命令

    我已经安装了spyderpip3 install spyder在苹果电脑上 但是 当我无法从 bash 启动它时 它会显示spyder command not found 我已按照其说明进行操作Github页面 https github c
  • 通过shell脚本进行串口控制

    我正在开发一个方向控制器 我有一个开发板 它通过 I2C 与传感器 指南针 通信 由于主板非常有限 没有操作系统 我开发了一个简单的程序来接收以下内容 1 get 0 读取传感器的寄存器 0 2 set 0 10 将传感器的寄存器 0 设置
  • 如何在不同目录中启动多个窗口的 tmux?

    我想使用脚本打开一个有 6 个窗口的 tmux 会话 每个窗口位于不同的目录中 我开始于我找到的一个脚本 http blog hawkhost com 2010 07 02 tmux E2 80 93 the terminal multip
  • bash循环跳过注释行

    我正在循环文件中的行 我只需要跳过以 开头的行 我怎么做 bin sh while read line do if line doesn t start with then echo line fi done lt tmp myfile 谢
  • 如何检测脚本是否正在被获取

    我有一个脚本 我不希望它调用exit如果它正在被采购 我想检查一下是否 0 bash但是如果脚本源自另一个脚本 或者用户从不同的 shell 获取它 例如ksh 有没有可靠的方法来检测脚本是否来源 稳健的解决方案bash ksh zsh 包
  • 以受限用户身份运行 monit 并使其监视需要 root 权限的进程

    我有一个用 Ruby 编写的特定脚本 需要 root 权限 大多数其他进程不需要它 因此很容易在 Monit 中设置 不是这个 服务器需要监听386 这个端口只有root可用 我不会详细说明原因 因为 1 我不是一个低级的人 2 到目前为止
  • 为什么我的 Dockerfile CMD 不起作用?

    所以在我的 Dockerfile 的末尾我有这样的内容 WORKDIR home CMD django admin startproject whattt CMD bin bash 当我创建映像然后运行容器时 一切都按预期运行 没有错误 D
  • 监听外部事件。 Bash 到 NodeJS 的桥梁

    在 NodeJS 进程内部 我如何监听来自 bash 的事件 例如 NodeJS side obj on something function data console log data Bash side do something Hel
  • 如何将后台作业的输出分配给 bash 变量?

    我想在 bash 中运行后台作业并将其结果分配给一个变量 我不喜欢使用临时文件 并且希望同时运行多个类似的后台任务 root root var echo hello world root root echo var hello world
  • 如何让 STDOUT 和 STDERR 都转到终端和日志文件?

    我有一个脚本 将由非技术用户交互式运行 该脚本将状态更新写入 STDOUT 以便用户可以确定脚本运行正常 我希望将Stdout和STDERR重定向到终端 以便用户可以看到脚本正在工作 并查看是否存在问题 我还希望将两个流都重定向到日志文件
  • 如何使用 echo 写入非 ASCII 字符?

    如何写非ASCII http en wikipedia org wiki ASCII使用 echo 的字符 是否有转义序列 例如 012或类似的东西 我想使用以下方法将 ASCII 字符附加到文件中 echo gt gt file 如果您关
  • 在 BASH 脚本中使用字符串作为变量名

    我有以下内容 bin sh n fred bob f n echo f 我需要在替换后执行底线 echo n 有办法做到这一点吗 我刚刚得到 test sh line 8 f bad substitution 在我这边 您可以像这样使用数组
  • 如何退出bash中的所有调用脚本?

    假设我有以下脚本 a sh echo in a if test 1 ne 2 then echo oops exit 1 fi b sh echo in b a sh echo in b 2 运行 b sh 时 如果 a sh 退出 我希望
  • Bash 和双引号传递给 argv

    我重新设计了这个示例以使其简单 但我想做的是在 bash shell 执行它时获取一个嵌套双引号字符串作为单个 argv 值 这是脚本示例 set x command1 key1 value1 key2 value2 key3 value3
  • Python bash 管道

    我想将 python 脚本的输出通过管道传输到 bash 脚本 到目前为止我所做的是尝试使用os popen sys subprocess 并试图给出一个管道的例子 os popen echo P 1 1 591336 4927369 1

随机推荐