Nextcloud挂载Webdav文件

一、安装Alist

参考文章:

https://alist.nn.ci/guide/install/manual.html

下载 alist-linux-amd64.tar.gz 最新版并解压

tar -zxvf alist-linux-amd64.tar.gz

注册一个服务来启停alist

sudo vi /usr/lib/systemd/system/alist.service

内容:

[Unit]
Description=alist
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/alist
#WorkingDirectory=/root/alist
ExecStart=/opt/alist/alist server
#ExecStart=/root/alist/alist server
Restart=on-failure

[Install]
WantedBy=multi-user.target

其中WorkingDirectory为可执行alist所在目录路径,ExecStart为可执行alist本身的路径。

然后就可以使用systemctl进行启停。

首次启动可使用

systemctl status alist 

查看admin登录密码,如果没记录下来只能设置一个新密码

./alist admin set NEW_PASSWORD

二、登录Alist并挂载网盘

(略)

三、挂载webdav到本地

安装davfs2

sudo yum install davfs2

创建待挂载目录

mkdir -p /home/ohmmx/cloud

挂载webdav

mount -t davfs http://127.0.0.1:5244/dav /home/ohmmx/cloud

输入用户名 admin,和密码,挂载完成。

四、将照片目录软链接到nextcloud目录下

将网盘的相册链接到某用户下

ln -s /home/ohmmx/cloud/photo /home/ohmmx/nextcloud/data/userA/files

五、使用nextcloud的occ工具扫描文件

先赋权,nginx启动用户,该用户见nginx配置说明,默认nginx

sudo chown -R nginx:nginx /home/ohmmx/nextcloud/data/userA/files/

再通过occ工具进行扫描

cd /home/ohmmx/nextcloud
sudo -u nginx php occ files:scan --all

最后,也是最重要的一点:

nextcloud不支持软链接,目前这个方案只能等待新版本的实现了。

发表在 技术, 服务器 | 标签为 , | 留下评论

ORDER BY 将空值NULL排到最后

在 ORDER BY 的时候,默认将NULL排在最前面,我们要将他们排到后面去。

ORDER BY col IS NULL, col DESC

或者加一个为空的判断,就能主动控制往前排还是往后排。(IFNULL参数1为空返回参数2)

ORDER BY IFNULL(col, 0) DESC, col DESC

或者(ISNULL参数1为空返回1,不为空返回0)

ORDER BY ISNULL(col) ASC, col DESC

或者(IF参数1为真返回参数2,为假返回参数3)

ORDER BY IF(ISNULL(col), 0, 1) DESC, col

效率比较

IFNULL() > IS NULL > ISNULL()
发表在 SQL, 数据库 | 标签为 , | 留下评论

Hibernate命名策略:逻辑名称

接上文 Hibernate命名策略:物理名称

参考文章 Hibernate 5 naming strategy examples

Spring Boot 配置项:

spring.jpa.hibernate.naming.implicit-strategy

该配置项有5个值,见下面的默认实现类和4个扩展实现类。

使用 PhysicalNamingStrategyStandardImpl  直接映射表名和字段名,不进行驼峰转换。

逻辑名称实现接口

org.hibernate.boot.model.naming.ImplicitNamingStrategy

默认实现类

org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

该实现类又扩展出以下几个实现类

org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

其中三个是由Hibernate实现,另一个由SpringBoot实现。

接下来看看他们之间的区别:

首先定义一个嵌入元素类,其中一个字段使用 Column 注解明确写明字段,另一个字段不使用注解。

@Embeddable

public class EmbeddableElement {

	@Column(name = "quoted_field")
	private String quotedField;

	private String regularField;

	// getter and setter
}

定义三个实体类:

基础表和链接表

@Entity
public class OwnedEntity {
	@Id
	private Long id;

	@ElementCollection
	@CollectionTable
	Set<EmbeddableElement> ownedElements;

	// getter and setter
}

一对多表

@Entity
@Table(name = "mainTable")
public class MainEntity {
	@Id
	private long id;

	@ElementCollection
	private Set<EmbeddableElement> mainElements;

	@OneToMany(targetEntity = DependentEntity.class)
	Set<DependentEntity> dependentEntities;

	@OneToOne(targetEntity = OwnedEntity.class)
	OwnedEntity ownedEntity;

	// getter and setter
}

多对一表

@Entity
@Table(name = "dependentTable")
public class DependentEntity {
	@Id
	private long id;

	@ManyToOne
	MainEntity mainEntity;

	@ElementCollection
	@CollectionTable(name = "dependentElements")
	Set<EmbeddableElement> dependentElements;

	// getter and setter
}

首先看基类 ImplicitNamingStrategyJpaCompliantImpl,得到建表语句如下:

CREATE TABLE OwnedEntity (id BIGINT NOT NULL, PRIMARY KEY (id));
CREATE TABLE OwnedEntity_ownedElements (OwnedEntity_id BIGINT NOT NULL, quoted_field VARCHAR(255), regularField VARCHAR(255));

CREATE TABLE mainTable (id BIGINT NOT NULL, ownedEntity_id BIGINT, PRIMARY KEY (id));
CREATE TABLE MainEntity_mainElements (MainEntity_id BIGINT NOT NULL, quoted_field VARCHAR(255), regularField VARCHAR(255));
CREATE TABLE mainTable_dependentTable (MainEntity_id BIGINT NOT NULL, dependentEntities_id BIGINT NOT NULL, PRIMARY KEY (MainEntity_id, dependentEntities_id));

CREATE TABLE dependentTable (id BIGINT NOT NULL, mainEntity_id BIGINT, PRIMARY KEY (id));
CREATE TABLE dependentElements (DependentEntity_id BIGINT NOT NULL, quoted_field VARCHAR(255), regularField VARCHAR(255));

Hibernate 原始命名策略 ImplicitNamingStrategyLegacyHbmImpl (仅区别语句)

CREATE TABLE mainTable_dependentEntities (MainEntity_id BIGINT NOT NULL, dependentEntities BIGINT NOT NULL, PRIMARY KEY (MainEntity_id, dependentEntities));

区别在于关联表名后缀不是 Table 而是 Entities

JPA命名策略 ImplicitNamingStrategyLegacyJpaImpl (仅区别语句)

CREATE TABLE mainTable_mainElements (mainTable_id BIGINT NOT NULL, quoted_field VARCHAR(255), regularField VARCHAR(255));

区别在于关联表主名后缀不是 Entity,而是 Table

策略 ImplicitNamingStrategyComponentPathImpl (仅区别语句)

CREATE TABLE MainEntity_mainElements (MainEntity_id BIGINT NOT NULL, quoted_field VARCHAR(255), mainElements_regularField VARCHAR(255));

区别在于嵌入式关联表中没有明确写明字段名的字段会添加属性名称前缀

策略 SpringImplicitNamingStrategy (仅区别语句)

CREATE TABLE mainTable_dependentEntities (MainEntity_id BIGINT NOT NULL, dependentEntities_id BIGINT NOT NULL, PRIMARY KEY (MainEntity_id, dependentEntities_id));

与 Hibernate 原始命名策略的区别仅在于关联表的字段多加后缀 _id

strategyprimaryTablejoinTablecollectTable
ImplicitNamingStrategyJpaCompliantImplEntity类名Entity物理名称 + 引用Entity的物理名称Entity类名 + 属性名称
ImplicitNamingStrategyLegacyHbmImplEntity物理名称 + 属性名称
ImplicitNamingStrategyLegacyJpaImplEntity物理名称 + 属性名称
ImplicitNamingStrategyComponentPathImplEntity属性名称 + 属性名称
SpringImplicitNamingStrategyEntity的物理名称 + 属性名称
发表在 JAVA, 数据库 | 标签为 , | 留下评论

Hibernate命名策略:物理名称

在 Spring Boot 开启自动更新数据库时:

spring.jpa.hibernate.ddl-auto: update

Spring Boot 配置项:

spring.jpa.hibernate.naming.physical-strategy

该配置项有2个值:

org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy (spring boot 2.6.0 之前)
org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy (spring boot 2.6.0含 之后)

以上两类都是实现了

org.hibernate.boot.model.naming.PhysicalNamingStrategy

其中前者 PhysicalNamingStrategyStandardImpl 为直接映射表名和字段名

在有注解@Table和@Column时,表名和字段名为设置的名称。没有配置时,表名为类名,字段名为类的字段名。

后者 CamelCaseToUnderscoresNamingStrategy 为驼峰命名,表名和字段名在有大写字母的情况下会在数据库自动转换为下划线 “_”

发表在 JAVA, 数据库 | 标签为 , | 一条评论

简单添加WordPress备案信息的方法

不折腾那些乱七八糟的,什么组件插件小工具之类的。

直接修改源码:

先确定当前网站使用的是哪个主题,我这里使用的是 twentyten,找到对应的路径:

wordpress/wp-content/themes/twentyten/

修改页脚文件:

vim footer.php

找到 site-info 对应的 div 在里面找个地方填上备案信息

<a href="https://beian.miit.gov.cn" target="_blank">京ICP备12345678号</a>

好处是很快很简单;缺点是主题如果更新或者更换主题需要重改。

发表在 服务器 | 标签为 , | 留下评论

一个简单的Jenkins流水线配置

上次使用了脚本来进行项目构建和发布;

这次使用Jenkins来干同样一件事。

直接上代码,具体含义请查询相关文档:

try {
    node {
        stage('Environment') {
            env.JAVA_HOME="${tool 'Java'}"
            env.PATH="${env.PATH}:${JAVA_HOME}/bin:${tool 'Gradle'}/bin"
            echo "PATH=${PATH}"
            echo "USER_HOME=${USER_HOME}"
        }
        stage('Source') {
            git branch: 'master', credentialsId: '9e133113-0dda-4072-8d4a-2477e5fc9bf1', url: 'https://github.com/ohmmx/testproject.git'
        }
        stage('Build') {
            sh "gradle :prj-tomcat:war :prj-springboot:bootJar"
            sh "cp -f ${JENKINS_HOME}/workspace/jenkins-project/prj-tomcat/build/libs/prj-tomcat.war ${USER_HOME}/deploy/tomcat/webapps/ROOT.war"
            sh "cp -f ${JENKINS_HOME}/workspace/jenkins-project/prj-springboot/build/libs/prj-springboot.jar ${USER_HOME}/deploy/prj-springboot.jar"
        }
    }
} catch (err) {
    currentBuild.result = "FAILURE"
    echo err
} finally {
    node {
        stage('Stop') {
            sh "fuser -k 8080/tcp || true"
            sh "fuser -k 9080/tcp || true"
        }
        stage('Start') {
            parallel (
                tomcat: {
                    echo "Ready to start prj-tomcat ......"
                    sh "JENKINS_NODE_COOKIE=dontKillMe ${USER_HOME}/deploy/tomcat/bin/startup.sh"
                },
                springboot: {
                    echo "Ready to start prj-springboot ......"
                    sh "JENKINS_NODE_COOKIE=dontKillMe nohup java -Dprofile=dev -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=29080 -Dserver.port=9080 -jar ${USER_HOME}/deploy/prj-springboot.jar &"
                }
            )
        }
    }
}

其中:

credentialsId 是在 Jenkins 里配置 Git 的用户名密码后,由 Jenkins 生成的用户ID。

JENKINS_HOME 路径默认为 /var/lib/jenkins/

jenkins-project 为 Jenkins 任务的名称(建议不要使用中文)

发表在 JAVA | 标签为 , , | 留下评论

Nginx整合PHP

安装PHP

从网站 http://rpms.remirepo.net/enterprise/ 找到系统对应的rpm

现在是CentOS8,这里使用 http://rpms.remirepo.net/enterprise/remi-release-8.rpm

sudo dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

查看是否安装成功:

sudo yum repolist

显示有 remi-modular 和 remi-safe 就表示安装成功了!

查看可以安装的版本:

sudo dnf module list php

找到需要安装的版本,并记下Stream列对应的名称,比如8.0版本就有两个选择 8.0 和 remi-8.0

设定PHP版本:

sudo dnf module reset php
sudo dnf module enable php:remi-8.1

安装PHP

sudo dnf -y install php
sudo dnf -y install php php-gd php-mysqlnd

其中后面几个模块是WordPress所需要的,可以酌情安装。

配置php-fpm,配置文件 /etc/php-fpm.d/www.conf,调整如下行的设置,与nginx启动用户一致:

user = username
group = group

启动php-fpm

sudo systemctl enable --now php-fpm

配置Nginx

以 WordPress 为例

设置nginx启动用户和组,配置文件 /etc/nginx/nginx.conf

# user nginx; 这个是默认用户,如果这里不调整php-fpm的配置就要设置成nginx
user username group;

在nginx的配置目录下 /etc/nginx/conf.d/ 新建一个配置文件 wordpress.conf

server {
        listen      2000;
        server_name wordpress.site.com;

        location / {
                root   /home/wordpress;
                index  index.php index.html index.htm;
                autoindex off;
                autoindex_exact_size off;
                autoindex_localtime on;
        }

        location ~ \.php$ {
                try_files      $uri = 404;
                root           /home/wordpress;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
                include        fastcgi_params;
        }
}

WordPress里的文件也要设置为同样的用户。

chown -R username:group /home/wordpress

可能遇到的问题

Nginx 和 php-fpm 一定要设置相同的用户名和组,不然会文件权限不足。

下面这个问题的原因是路径上的目录没有访问权限

open() "/var/lib/nginx/tmp/fastcgi/2/00/0000000002" failed (13: Permission denied)

把 fastcgi 目录的权限设置为755就好了。

发表在 服务器 | 标签为 , | 留下评论

一组服务器构建发布启停脚本

背景:功能开发完成以后需要在测试服务器发布,有几种方案可选。

其中一种是使用Jenkins,而另一种是使用脚本,这次就先使用脚本。

开始以前需要准备以下环境:

$HOME/bin 目录, 用于存放脚本
$HOME/build 目录, 用于存放源码
$HOME/deploy 目录, 用于进行发布
$HOME/deploy/tomcat 目录, Tomcat目录, 可以是软链接

首先准备源码

cd $HOME/build
git clone https://github.com/ohmmx/testproject.git

准备分支存储文件,用于存放需要切换至的分支,不必每次手动切换

vim $HOME/bin/branch

填写分支名
master
保存退出 :wq

编写构建打包脚本:

vim $HOME/bin/build.sh
#!/bin/bash

branch=`cat branch`

cd $HOME/build/testproject
git fetch -p
git checkout $branch
brch=`git rev-parse --abbrev-ref HEAD`
echo -e "Publish in branch: \033[44;37m [$brch] \033[0m"
git pull --all

gradle clean :prj-tomcat:war :prj-springboot:bootJar

在构建时会已蓝底白字显示当前切换至的分支,避免分支填写出错。

其中Tomcat项目打包为war包,SpringBoot项目打包为Jar包。

编写Tomcat项目启动脚本:

其中8080为启动端口,可以在 $HOME/deploy/tomcat/conf/server.xml 的 Connector protocol=”HTTP/1.1″ 部分找到并设置

vim $HOME/bin/start-tomcat.sh
#!/bin/bash

# 停止服务
fuser -k 8080/tcp || true

rm -rf $HOME/deploy/tomcat/webapps/ROOT
rm -f $HOME/deploy/tomcat/webapps/ROOT.war

cp $HOME/build/testproject/prj-tomcat/build/libs/prj-tomcat.war $HOME/deploy/tomcat/webapps/ROOT.war

cd $HOME/deploy/tomcat/bin/

./startup.sh

编写SpringBoot项目启动脚本:(其中9081为启动端口)

vim $HOME/bin/start-springboot.sh
#!/bin/bash

# 停止服务
fuser -k 9080/tcp || true

rm -f $HOME/deploy/prj-springboot.jar
cp $HOME/build/testproject/prj-springboot/build/libs/prj-springboot.jar $HOME/deploy/

nohup java -Dserver.port=9080 -jar $HOME/deploy/prj-springboot.jar

进阶版-Tomcat篇:

Tomcat设置内存大小:

vim $HOME/deploy/tomcat/bin/setenv.sh
#!/bin/bash

CATALINA_OPTS=" -Xms512m -Xmx512m"

Tomcat设置JPDA启动:

vim $HOME/deploy/tomcat/bin/catalina.sh

在开头的一堆注释下面加入以下一行:(其中28080为JPDA端口)

JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=28080,server=y,suspend=n"

然后使用JPDA方式启动:

vim $HOME/deploy/tomcat/bin/startup.sh

最后一行

exec "$PRGDIR"/"$EXECUTABLE" start "$@"

修改为

exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"

进阶版-SpringBoot篇:

设置启动内存,添加参数 -Xmx1024m

设置指定profile配置启动 -Dspring.profiles.active=dev

避免打印nohup日志,在脚本最后添加 > /dev/null 2>&1 &

使用JPDA方式启动 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=29080

所以最终的结果是这样的:

普通启动

#!/bin/bash

# 停止服务
fuser -k 9080/tcp || true

rm -f $HOME/deploy/prj-springboot.jar
cp $HOME/build/testproject/prj-springboot/build/libs/prj-springboot.jar $HOME/deploy/


nohup java -Xmx1024m -Dspring.profiles.active=dev -Dserver.port=9080 -jar $HOME/deploy/prj-springboot.jar > /dev/null 2>&1 &

JPDA启动

#!/bin/bash

# 停止服务
fuser -k 9080/tcp || true

rm -f $HOME/deploy/prj-springboot.jar
cp $HOME/build/testproject/prj-springboot/build/libs/prj-springboot.jar $HOME/deploy/

nohup java -Xmx1024m -Dspring.profiles.active=dev -Dserver.port=9080 -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=29080 -jar $HOME/deploy/prj-springboot.jar > /dev/null 2>&1 &
发表在 JAVA | 标签为 , , | 留下评论

Gradle安装说明(手动版)

我们按照上次安装Java的方法安装Gradle。

首先从Gradle官网下载压缩包binary-only得到了一个zip文件gradle-0.0.0-bin.zip

https://gradle.org/releases/

我们可以将Gradle解压到Java目录

sudo unzip gradle-0.0.0-bin.zip -d /opt/java/

然后建立软链接

sudo ln -s /opt/java/gradle-0.0.0 /opt/java/gradle

最后配置profile

sudo vim /etc/profile.d/gradle.sh

脚本内容:

#!/bin/bash

export GRADLE_HOME=/opt/java/gradle

export PATH=$PATH:$GRADLE_HOME/bin

重新登录用户检查一下

gradle -v

收工

发表在 JAVA | 标签为 , , | 留下评论

简易JDK安装说明(手动版)

我们选择使用压缩包进行安装,而不是rpm,方便操作。

先从官网下载最新的Java 8: x64 Compressed Archive

https://www.oracle.com/java/technologies/downloads/

下载后我们得到了一个压缩包:jdk-8u000-linux-x64.tar.gz

其中000为小版本号。

或者我们可以下载历史版本,进入页面 Java archive

说明一下:

8u211 和之前的版本为BCL协议,免费使用;

8u202和之后的版本为OTN协议,也是免费使用,但是Oracle随时可以凭此协议找你要钱,差不多就是这个意思。具体协议差异可以自行了解。

我们个人(非商业)直接使用最新版就OK了。

先使用sudo权限创建一个JAVA的根目录:

sudo mkdir -p /opt/java

再将下载的压缩包解压到JAVA目录:

sudo tar -zxvf jdk-8u000-linux-x64.tar.gz -C /opt/java/

建立软链接(以后更换或者升级JDK,直接修改此软连接,是不是非常的方便):

sudo ln -s /opt/java/jdk1.8.0_000 /opt/java/jdk

配置profile加载JDK(如果以后不想要JDK了,直接删除此配置就OK了):

sudo vim /etc/profile.d/java.sh

脚本内容:

#!/bin/bash

export JAVA_HOME=/opt/java/jdk

export PATH=$PATH:$JAVA_HOME/bin

好了,用户重新登录一下检查是否成功

java -version

行了,大功告成!

发表在 JAVA | 标签为 , , | 留下评论