0%

stm32开发环境搭建(mac)

环境工具

  • CLion
  • STM32CubeMX 记录见:mac系统安装STM32CubeMX
  • Segger 下载 Ozone - The J-Link Debugger
  • 安装编译器:arm-gcc-none-eabi-gcc brew cask install gcc-arm-embedded
  • 安装stlinkbrew install stlink
  • 安装openocd 执行brew install openocd

运行测试第一个跑马灯

环境准备

  • mac os系统

  • 开发板NUCLEO-F401RE 其中mcu型号stm32f401RETx

  • 安装项目初始化软件STM32CubeMX 步骤见mac系统安装STM32CubeMX

  • 安装编译器arm-gcc-none-eabi-gcc 执行brew cask install gcc-arm-embedded

  • 安装stlink下载器brew install stlink

  • 开发板NUCLEO-F401RE跳线如图

    62fMm8.png

项目搭建步骤:

  1. 初始化项目工程见STM32CubeMX使用之初始化项目

  2. 进入生成的工作目录执行make

  3. 提示错误/bin/sh: /arm-none-eabi-gcc: No such file or directory解决,修改Makefile

    1
    2
    # BINPATH是指arm-none-eabi-gcc的路径,可以通过执行which arm-none-eabi-gcc得到路径
    BINPATH = /usr/local/bin/
  4. 提示错误

    1
    2
    build/main.o: In function `main':
    /Users/xuanleung/IdeaProjects/f401demo/Src/main.c:75: multiple definition of `main'

    解决修改Makefile,删除里面重复的,#标注为有重复,删除即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    C_SOURCES =  \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c \
    #Src/stm32f4xx_it.c \
    Src/stm32f4xx_it.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c \
    /Src/system_stm32f4xx.c \
    #Src/stm32f4xx_hal_msp.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c \
    #Src/main.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c \
    Src/stm32f4xx_hal_msp.c \
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c \
    Src/main.c
  5. 再重新执行make,得到编译成功的文件了

    1
    2
    3
    4
    5
    /usr/local/bin//arm-none-eabi-size build/f401demo.elf
    text data bss dec hex filename
    5460 20 1636 7116 1bcc build/f401demo.elf
    /usr/local/bin//arm-none-eabi-objcopy -O ihex build/f401demo.elf build/f401demo.hex
    /usr/local/bin//arm-none-eabi-objcopy -O binary -S build/f401demo.elf build/f401demo.bin
  6. 下载bin文件到开发板NUCLEO-F401RE ,执行st-flash write ./build/xxxxx.bin 0x8000000,如果下载失败重启单片机和检查跳线帽

  7. 修改src下面的main.c添加跑马灯代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    while (1)
    {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    HAL_Delay(500);
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
    HAL_Delay(500);
    }
  8. 重新编译make和下载st-flash write ./build/f401demo.bin 0x8000000

  9. 下载完成后ld2就会闪烁

使用CLion进行项目编译运行

操作记录:mac下stm32CubeMX+CLion+openocd开发环境

  1. 使用STM32CubeMX重新初始化项目,选择SW4STM32

问题

debug提示如下错误:

1
Cannot load symbol file: "/Users/xuanleung/IdeaProjects/f401re_demo/cmake-build-debug/f401re_demo.elf": not in executable format: File format not recognized

解决:取消勾选

62fsh9.png

参考

macOS 下用 Clion和OpenOCD开发 STM32(st-link和STM32CubeMX)

CLion for embedded development

CLion for Embedded Development Part II

http://blog.meekdai.com/MacOS-Eclipse-ARM-GCC-STM32.html

STM32 Nucle o-64 boards文档

Nucleo-64板载ST-LINK/ V2-1调试器 之对外界编程

jenkins使用pipeline

脚本名词解释

pipeline <必须> Pipeline是CD管道的用户定义模型。Pipeline的代码定义了您的整个构建过程,通常包括构建应用程序,测试和交付应用程序的阶段。
agent <必须> 定义pipeline的执行环境,必须存在
stages<阶段> 包含多个子阶段stage(‘子阶段名’)

jenkins 的工作空间目录 /var/jenkins_home/workspace/

node vs agent 区别

agent是声明性的pipelines,node是脚本性的pipelines

实践

pipeline使用gradle

学习到如何使用工具,和配置工具全局变量

  1. 配置工具系统管理->全局工具配置->Gradle->Gradle 安装

    name:gradle4.8

    • 自动安装

    版本 Gradle 4.8

    Apply->Save即可

    注释:如果没有Gradle设置,先去安装Gradle插件,默认推荐设置是安装了的

  2. 编写Jenkinsfile进行测试

    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env groovy Jenkinsfile
    node {
    def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
    env.PATH = "${gradleHome}/bin:${env.PATH}"
    stage('build') {
    sh 'gradle -v'
    }
    }

pipeline使用gradle打包java spring boot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
//sh './gradlew clean :eurekaserver:build' //这里会自动下载项目里的gradle版本(4.7)
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
// bat 'gradlew.bat clean :eurekaserver:build'
bat 'gradle clean :eurekaserver:build'
}
}
}

打包jar为镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
//sh './gradlew clean :eurekaserver:build' //这里会自动下载项目里的gradle版本(4.7)
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
// bat 'gradlew.bat clean :eurekaserver:build'
bat 'gradle clean :eurekaserver:build'
}
}
stage('docker build image'){
dir('eurekaserver'){ //dockerfile的跟目录
docker.build("springcould/eurekaserver:${env.BUILD_NUMBER}")
}
}
}

运行镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env groovy Jenkinsfile
node {
def gradleHome = tool 'gradle4.8' //这里的gradle4.8要和gradle工具的配置里的name要一致
env.PATH = "${gradleHome}/bin:${env.PATH}"
stage('gradle build') {
if (isUnix()) {
sh 'gradle clean :eurekaserver:build' //使用jenkns安装的gradle工具(4.8)
} else {
bat 'gradle clean :eurekaserver:build'
}
}
stage('docker build image'){
dir('eurekaserver'){ //dockerfile的跟目录
docker.build("springcould/eurekaserver:${env.BUILD_NUMBER}")
}
}
stage('docker run Application'){
sh "docker run -p 8091:8091 springcould/eurekaserver:${env.BUILD_NUMBER}"
}
}

pipeline 环境变量选择设置

**严重注意**这个需要第二次运行才会生效,第一次设置之后运行,不会出来,第二次拉去运行才会出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env groovy Jenkinsfile
pipeline {
agent any
parameters {
choice(name: 'door_choice',
choices: 'one\ntwo\nthree\nfour',
description: 'What door do you choose?')
}
stages {
stage('build') {
steps {
echo "${params.door_choice}"
}
}
}
}

pipeline agent版gradle脚本

not support tool "gradle4.8"单个设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env groovy Jenkinsfile
pipeline {
agent any
parameters {
choice(name: 'door_choice',
choices: 'one\ntwo\nthree\nfour',
description: 'What door do you choose?')
}
stages {
stage('build') {
tools{
gradle "gradle4.8"
}
steps {
echo "${params.door_choice}"
sh 'gradle -v'
}
}
}
}

申明式使用脚本式语言script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env groovy Jenkinsfile

pipeline {
agent any
parameters {
choice(name: 'project_choice',
choices: 'eurekaserver\neurekaclient\neurekafeign\neurekazuul',
description: '你要编译构建那个项目?')
}
stages {
stage('docker build'){
steps{
dir("${params.project_choice}"){
sh "pwd"
script { //需要用script包裹,就能使用脚本式语言
docker.build("my-image:${env.BUILD_ID}")
}
}
}
}
}
}

环境变量

env.BUILD_ID 当前的编译id,和Jenkins versions 1.597+ 的env.BUILD_NUMBER一样

env.JOB_NAME 当前项目名

env.JENKINS_URL only available if Jenkins URL set in “System Configuration”

git diff HEAD^ eurekaserver/ 和上个版本比较eurekaserver目录,可以不要

参考

https://github.com/arun-gupta/docker-jenkins-pipeline

参考工具

github: osmdroid/osmdroid

compile 'org.osmdroid:osmdroid-android:<VERSION>'

离线地图制作工具: Mobile Atlas Creator

使用Mobile Atlas Creator

wiki map sources

离线地图工具类SampleOfflineOnly.java

离线地图官方教程Offline-Map-Tiles

操作步骤

离线地图制作
  1. 打开Mobile Atlas Creator工具
  2. 新建地图册(可选Osmdroid ZIP/SQLite/GEMF)
  3. 选择地图源
  4. 勾选图片转换,设置图块格式(重要,要和代码的设置一致)
  5. 设置缩放比例
  6. 地图上框选区域
  7. 在当前地图册点击添加选择区域
  8. 最后开始点击下载地图册
  9. 得到一个压缩文件,存储备用
离线地图自定义地图源(geoserver)
  1. Mobile Atlas Creator工具目录的mapsources目录添加地图源配置文件

  2. geoserver地图地图源配置文件geoserver_maps.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <customWmsMapSource>
    <name>My Geoserver WMS</name>
    <minZoom>0</minZoom>
    <maxZoom>18</maxZoom>
    <tileType>PNG</tileType>
    <version>1.1.1</version>
    <!-- 图层名字hws(工作空间):china_net(图层名字) -->
    <layers>hws:china_net</layers>
    <!-- hws替换为自己的工作区间,ip端口替换自己服务器的,其他不变 -->
    <url>http://192.168.1.230:8082/geoserver/hws/wms?service=WMS&amp;</url>
    <!-- 投影坐标系 -->
    <coordinatesystem>EPSG:4326</coordinatesystem>
    <aditionalparameters></aditionalparameters>
    <backgroundColor>#000000</backgroundColor>
    </customWmsMapSource>
  3. 多图层配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <customMultiLayerMapSource>
    <name>多图层自定义</name>
    <tileType>png</tileType>
    <backgroundColor>#000000</backgroundColor>
    <!-- 0~1由透明到不透明,1.0是设置对底层的图层,0.5是设置底层上一层图层,以此类推n图层以此设置即可-->
    <layersAlpha>1.0 1.0 0.5 1.0</layersAlpha>
    <layers>
    <customMapSource>
    <name>Google 卫星图</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <url>http://mt0.google.cn/vt/lyrs=s@124&amp;hl=zh-CN&amp;gl=CN&amp;src=app&amp;x={$x}&amp;s=&amp;y={$y}&amp;z={$z}&amp;s=Galileo</url>
    <backgroundColor>#000000</backgroundColor>
    </customMapSource>

    <customMapSource>
    <name>Google 地名图</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <url>http://mt0.google.cn/vt/imgtp=png32&amp;lyrs=h@207000000&amp;hl=zh-CN&amp;gl=CN&amp;src=app&amp;x={$x}&amp;y={$y}&amp;z={$z}&amp;s=Galil</url>
    </customMapSource>

    <customWmsMapSource>
    <name>林班界</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <layers>hws:linbanjie</layers>
    <url>http://192.168.1.230:8082/geoserver/hws/wms?service=WMS&amp;transparent=TRUE&amp;</url>
    <!-- 投影坐标系 -->
    <coordinatesystem>EPSG:4326</coordinatesystem>
    <aditionalparameters></aditionalparameters>
    </customWmsMapSource>

    <customWmsMapSource>
    <name>巡护路线</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <!-- 图层名字hws(工作空间):china_net(图层名字) -->
    <layers>hws:xunhuluxian</layers>
    <!-- hws替换为自己的工作区间,ip端口替换自己服务器的,其他不变 -->
    <!-- 多参数,每个参数用&amp;分开-->
    <!-- 背景设置透明transparent=TRUE-->
    <url>http://192.168.1.230:8082/geoserver/hws/wms?service=WMS&amp;transparent=TRUE&amp;</url>
    </customWmsMapSource>
    </layers>
    </customMultiLayerMapSource>
离线地图自定义地图源(google地图)
  1. Mobile Atlas Creator工具目录的mapsources目录添加地图源配置文件

  2. google地图地图源配置文件google_maps.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <customMultiLayerMapSource>
    <name>Google 卫星</name>
    <tileType>PNG</tileType>
    <layers>
    <customMapSource>
    <name>Google 卫星图</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <url>http://mt0.google.cn/vt/lyrs=s@124&amp;hl=zh-CN&amp;gl=CN&amp;src=app&amp;x={$x}&amp;s=&amp;y={$y}&amp;z={$z}&amp;s=Galileo</url>
    <backgroundColor>#000000</backgroundColor>
    </customMapSource>
    <customMapSource>
    <name>Google 地名图</name>
    <minZoom>0</minZoom>
    <maxZoom>20</maxZoom>
    <tileType>PNG</tileType>
    <tileUpdate>None</tileUpdate>
    <url>http://mt0.google.cn/vt/imgtp=png32&amp;lyrs=h@207000000&amp;hl=zh-CN&amp;gl=CN&amp;src=app&amp;x={$x}&amp;y={$y}&amp;z={$z}&amp;s=Galil</url>
    </customMapSource>
    </layers>
    </customMultiLayerMapSource>
  3. 地图源文件xml的设置搜索Mobile Atlas Creator自定义地图源

    IPad 離線地圖:「Mobile Atlas Creator + 地圖加加」,讓google map成為好用的離線地圖!!

Android代码设置

  1. 导包compile 'org.osmdroid:osmdroid-android:<VERSION>'

  2. 手动设置离线地图的文件

    1
    2
    3
    4
    5
    6
    7
    //路径压缩包的路径放在存储目录下/osmdroid/Google Maps(世界墨卡托).zip这个是刚刚用工具制作得到的压缩文件
    String path=Environment.getExternalStorageDirectory().getAbsolutePath() + "/osmdroid/"+"Google Maps(世界墨卡托).zip";
    //设置为离线工作模式。路径一定要对,而且只支持 ZIP/SQLite/GEMF
    mapView.setTileProvider(new OfflineTileProvider(new SimpleRegisterReceiver(this),new File[]{new File(path)}));
    //这里Google Map为压缩文件的第一层目录名,一定要一致,.png.tile为最内层目录的文件后缀名一点定要一致,一般是png,这里比较特殊
    mapView.setTileSource(new XYTileSource("Google Map", 7, 16,
    256, ".png.tile", null));
  3. 上面那步基本就可以解析了,官方使用SampleOfflineOnly.java做自动解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    //设置离线地图的路径
    File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/osmdroid/");
    if (f.exists()) { //判断目录是否存在
    File[] list = f.listFiles(); //得到该目录下的文件
    if (list != null) {
    for (int i = 0; i < list.length; i++) { //遍历的得到的所有目录和文件
    if (list[i].isDirectory()) { //目录跳过
    continue;
    }
    String name = list[i].getName().toLowerCase();
    if (!name.contains(".")) { //没有后缀跳过
    continue; //skip files without an extension
    }
    name = name.substring(name.lastIndexOf(".") + 1); //得到后缀名
    if (name.length() == 0) {
    continue;
    }
    if (ArchiveFileFactory.isFileExtensionRegistered(name)) { //后缀名是否是ZIP/SQLite/GEMF其中一个
    try {
    OfflineTileProvider tileProvider = new OfflineTileProvider(new SimpleRegisterReceiver(this),
    new File[]{list[i]}); //如果是把该文件作为离线地图的提供者
    mapView.setTileProvider(tileProvider); // <重要>
    String source = "";
    IArchiveFile[] archives = tileProvider.getArchives();
    if (archives.length > 0) {
    Set<String> tileSources = archives[0].getTileSources();
    if (!tileSources.isEmpty()) {
    source = tileSources.iterator().next(); //活动压缩文件第一级目录的目录名
    //自定义设置 <重要> ,其中文件后缀名要和压缩文件内的后缀一致
    this.mapView.setTileSource(new FileBasedTileSource(source,0, 18, 256, ".png", null));
    // this.mapView.setTileSource(FileBasedTileSource.getSource(source)); //默认设置
    } else {
    this.mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
    }
    } else {
    this.mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
    }
    this.mapView.invalidate();
    return;
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }
    }
    }
    Toast.makeText(this, f.getAbsolutePath() + " did not have any files I can open! Try using MOBAC", Toast.LENGTH_SHORT).show();
    } else {
    Toast.makeText(this, f.getAbsolutePath() + " dir not found!", Toast.LENGTH_SHORT).show();
    }

常见问题

  1. 当mobac配置多图层时,geoserver wms不加transparent=TRUE&amp;会有白色背景,设置透明度会导致最底层的地图上覆盖了一层半透明的白色,导致看不起低图
  2. mobac加载geoserver gwc连接,如果图层只有一部分,会导致Google map在图层之外的也加载不出来
参考

How to use Custom map in MOBAC?

简介

官网

全平台通用数据库

  1. 特点自带通知
  2. 实体类方式

使用

  1. 在project中的build.gradle添加

    1
    2
    3
    dependencies {
    classpath "io.realm:realm-gradle-plugin:5.1.0"
    }
  2. 在model中的build.gradle添加

    1
    apply plugin: 'realm-android'
  3. 新建实体类,两种方式

    方式一

    1
    2
    3
    4
    5
    @RealmClass
    public class TestEntiy implements RealmModel {
    private Long id;
    ......
    }

    方式二

    1
    2
    3
    4
    public class TestEntiy extends RealmModel {
    private Long id;
    ......
    }
  4. 在application中初始化realm

    1
    2
    3
    4
    5
    6
    7
    Realm.init(context); //数据库初始化
    RealmConfiguration config = new RealmConfiguration.Builder().name("mulun.realm").build();
    Realm.setDefaultConfiguration(config); //设置配置,数据库文件名为mulun.realm
    //测试
    Realm realm = Realm.getDefaultInstance(); //获取数据库实例
    Log.i("MyApplication","数据库路径为:"+realm.getPath()); //打印路径
    realm.close(); //用完需要关闭实例
  5. 在data/data/包名/file目录下可以找到数据库文件mulun.realm

  6. 该文件可以通过Realm Studio打开

进阶

数据库插入/删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Realm realm = Realm.getDefaultInstance(); //获取数据库实例
//方式一
TestEntiy testEntiy=new TestEntiy();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealm(testEntiy);
}
});
//查询删除数据,该查询是异步的,如果数据testEntiy发生了修改和增加会在这里收到通知
realm.where(TestEntiy.class).findAllAsync().asFlowable().subscribe(new Consumer<RealmResults<TestEntiy>>() {
@Override
public void accept(final RealmResults<TestEntiy> testEntiy) throws Exception {
TestEntiy testEntiyRes = realm.copyFromRealm(testEntiy); //此种方式才能真正取到实体类,不能直接用testEntiy
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
testEntiy.deleteAllFromRealm(); //上传失败删除数据
}
});
}
}
realm.close();

另一种操作方式

1
2
3
4
5
Realm realm = Realm.getDefaultInstance(); //获取数据库实例
realm.beginTransaction();
realm.copyToRealm(testEntiy);
realm.commitTransaction();
realm.close();

简介

github文档:jenkinsci/docker

jenkins官网

Docker hub:jenkins/jenkins

蓝色主题版:jenkinsci/blueocean

安装

脚本文件https://github.com/xuanfong1/config/blob/master/dockerStack/stack-jenkins.yml

创建挂载目录

启动提示:

1
2
3
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied

Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

解决:执行chown -R 1000:1000 /dockerdata/v-jenkins/jenkins_home改变用户组为1000 用户1000

jenkins 之docker插件

docker-build-step 构建步骤使用docker命令

CloudBees Docker Build and Publish镜像构建以及推送仓库

Docker 远程连接docker进行代理构建

Docker API提供其他插件docker服务api

CloudBees Docker Custom Build Environment构建镜像或从仓库拉去镜像

Docker Swarm集群

https://github.com/boxboat/jenkins-demo

错误处理

  1. 连接错误,解决添加挂在卷"/var/run/docker.sock:/var/run/docker.sock"

    1
    2
    3
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

    script returned exit code 1
  2. 连接没权限,解决

    1
    2
    3
    Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.35/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&session=6ec5bc5a7afd427649abb0a03b733c9586dd9271474c89359e31a3910ed971e8&shmsize=0&t=e5e2d0e18760db6972a9c42a9a81653e633ff131&target=&ulimits=null: dial unix /var/run/docker.sock: connect: permission denied

    script returned exit code 1

    执行sudo ls -la /var/run/docker.sock

    1
    srw-rw----. 1 root docker 0 5月  15 16:36 /var/run/docker.sock

    --group-add=$(stat -c %g /var/run/docker.sock)

    sudo usermod -a -G docker jenkins

    解决方案

    方案一

    改变socke所属的用户组

    用root用户进入jenkins容器

    执行chown :jenkins /var/run/docker.sock

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -------------宿主机------------------------------
    [root@worker ~]# ls -la /var/run/docker.sock
    srw-rw----. 1 root docker 0 66 16:58 /var/run/docker.sock
    执行后
    [root@worker ~]# ls -la /var/run/docker.sock
    srw-rw----. 1 root 1000 0 66 16:58 /var/run/docker.sock
    ------------------jenkins容器---------------------
    srw-rw---- 1 root 994 0 Jun 6 08:58 var/run/docker.sock
    执行后
    srw-rw---- 1 root jenkins 0 Jun 6 08:58 var/run/docker.sock

    cat /etc/group查看用户组id

    自我理解:

    这里通过挂载卷的形式共享/var/run/docker.sock套接字,但是默认套接字属于root docker组,这里docker的组id为994,但是容器内没有994的组,所以直接显示994,最后执行这个chown :jenkins /var/run/docker.sock之后把组更改为乐jenkins组,但是默认宿主机是没有jenkins组,所以直接显示jenkins的id 1000,这里直接修改为jenkins用户组,虽然可以解决权限问题,不知道会不会影响其他的使用该sock套接字(隐患

    完善思路:

    新建个jenkins组

    添加docker用户到jenkins组

    但是发现

    宿主机id docker 没有docker用户

    且docker组没有任何用户,因此可以放心更改组,所以要不要新建组待考虑

    1
    2
    3
    4
    cat /etc/group #查看组信息
    cgred:x:995:
    docker:x:994:jenkins
    #组名:口令(默认空/*):组标识号(gid):组内用户列表
    方案二

    自我新思路

    宿主机创建个jenkins用户组指定id1000

    宿主机执行useradd -u 1000 jenkins

    然后执行sudo usermod -a -G docker jenkins

    失败,没有权限

    方案三(未实验)

    root用户可以访问docker,需要重写dockerfile

    1
    2
    FROM <base-image>
    USER root

    隐患:不知到用root用户登陆会不会影响jenkins的一些功能

    方案四(未实验)

    修改groupadd -g 994 docker,找不到命令

    然后执行usermod -a -G docker jenkins

    此法每次重启容器都会丢失配置,虽然可以通过挂载目录形式保存设置,太麻烦。

  3. Jenkins 第一次打开,一直显示启动中

    解决:

    修改jenkins_home/updates/default.json

    把 “connectionCheckUrl”:”http://www.google.com/" 改为 “connectionCheckUrl”:”http://www.baidu.com/"

    https://github.com/jenkinsci/docker/issues/263

centos 安装jenkins,需要jdk8

1
2
3
4
5
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins
sudo service jenkins start/stop/restart
sudo chkconfig jenkins on

简介

Apache Shiro是java的一个安全框架,和Spring Security比相对简单,功能简单,使用简单,适合小型简单的项目。

功能

  • Authentication:身份认证/登陆,验证用户身份
  • Authorization:授权,权限验证,验证已认证的用户是否拥有某个权限
  • session manager:会话管理
  • cryptography:加密
  • web support:web支持
  • caching:缓存
  • concurrency:多线程并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
  • testing:测试支持
  • run as:运行一个用户假装另一个用户的身份进行登陆
  • remember me:记住我密码功能

原理

graph LR
a[object/用户]-->b[SecurityManager/shiro]
b-->c[Realm/数据源]

简单体验登陆

  1. 在gradle引入依赖compile group: 'org.apache.shiro', name: 'shiro-core', version: '1.4.0'

  2. 在目录resources下新建一个shiro.ini文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # users 标签下面格式为
    # 用户名 = 密码,角色1,角色2,....,角色N
    [users]
    root = secret, admin
    guest = guest, guest
    test = 123456,test

    # roldes 角色标签下面格式为
    # 角色 = 权限1,权限2, ....权限N
    [roles]
    admin = *
  3. 创建登陆方法,IniSecurityManagerFactory该方法在1.4已经过期了,用下面的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini"); //此方法过期
    IniRealm iniRealm=new IniRealm("classpath:shiro.ini"); //读取shiro配置文件
    DefaultSecurityManager securityManager=new DefaultSecurityManager(iniRealm);
    SecurityUtils.setSecurityManager(securityManager);
    Subject currentUser=SecurityUtils.getSubject();
    if (!currentUser.isAuthenticated()){
    UsernamePasswordToken token=new UsernamePasswordToken("admin","1");
    token.setRememberMe(true);
    try {
    currentUser.login(token);
    }catch (UnknownAccountException una){
    System.out.print("用户名不存在"+una.getMessage());
    }catch (IncorrectCredentialsException ice){
    System.out.print("无效的认证"+ice.getMessage());
    }catch (LockedAccountException lae){
    System.out.print("你的账户被锁定"+lae.getMessage());
    }catch (AuthenticationException ae){
    System.out.print("未知错误"+ae.getMessage());
    }
    }

shiro名词概念解释

  • subject :当前操作的用户
  • SecurityManager :shiro框架核心,内部组件管理
  • realm : 连接桥梁,用于和用户数据,权限数据连接(来源文件、数据库)

xml配置

1
2
3
4
5
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms" ref="customRealm"/>
<property name="cacheManager" ref="cacheManager"/>
<property name="sessionManager" ref="sessionManager"/>
</bean>

数据库表设计:

1529049788944

参考

Shiro权限控制框架入门

配置方式一xml

在resources目录dubbo-provider.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--该提供者服务名称-->
<dubbo:application name="dubbo-provider"/>
<!--组播模式的注册中心,推荐用zookeeper-->
<!--<dubbo:registry address="zookeeper://10.14.1.7:2181"/>-->
<!--暴露的端口服务-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--声明暴露服务公共接口类-->
<dubbo:service interface="exxk.dubbo.commonimpl.DemoService" ref="demoService"/>
<!--提供者实现类-->
<bean id="demoService" class="exxk.dubbo.provider.impl.DemoServiceImpl"/>
</beans>

需要在dubbo启动器指向xml名字

1
2
3
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"dubbo-provider.xml"}); //读取dubbo配置文件
context.start();

配置方式二dubbo.properties

注:配置文件名字是固定的

1
dubbo.registry.address=zookeeper://10.14.1.7:2181

配置方式三jvm

注:gradle application task run启动vm设置无效

1
-Ddubbo.registry.address=zookeeper://10.14.1.7:2181

覆盖策略

JVM>XML>Properties其中jvm优先级最高