利用rsync断点续传scp中断的文件传输

服务器经常需要备份,但是长时间的下载,难免会出现下载中断的情况。

一直使用scp下载备份好的文件,以前数据量少的时候,直接重新下载就可以了。随着网站上数据越来越多,下载的时间越来越长,完全重新开始变得不现实了。有时候下载到90%以上的时候,失败了,完全重传是没有必要的。

我们只需要下载缺失的部分就好了,幸运的是rsync支持这种需求。

具体的做法是将如下的选项组合传递给rsync-checksum(文件分块计算校验和,只传输校验和不一致的部分),-in-place(将文件原地替换,因为rsync通常会写一个临时文件,然后移动)和-no-whole-file(告诉rsync不要复制整个文件,而是使用deltas(部分传输))。

例如:

$ rsync -Pa --checksum --inplace --no-whole-file --progress remote.server:file local.file

下面是一个真实的例子:

$ rsync -Pa --checksum --inplace --no-whole-file --progress -e 'ssh -p 22' user@www.mobibrw.com:~/backup/wordpress.20181203.tar.gz wordpress.20181203.tar.gz

receiving incremental file list
sent 19 bytes  received 76 bytes  0.22 bytes/sec
total size is 8379088896  speedup is 88200935.75

整个过程非常的快,比完全重传快多了。

scp命令拷贝文件非常好用,但在拷贝大文件时存在一个问题就是连接经常会断开,此时再使用scp进行拷贝会重新拷贝文件,为了解决这个问题。我们可以使用rsync命令来进行断点续传。命令如下:

$ rsync -P --rsh=ssh xxx.zip 192.168.0.1:~/

为了使用方便可以设置alias:

$ alias rscp="rsync -P --rsh=ssh"

参考链接


macOS Mojave(10.14.1)安装Vulkan依赖的工具链SPIR-V Toolchain

目前在研究学习VulkanVulkan使用SPIR-V工具链进行编译,在macOS Mojave(10.14.1)中使用如下命令安装工具链:

$ brew info glslang
glslang: stable 7.10.2984 (bottled), HEAD
OpenGL and OpenGL ES reference compiler for shading languages
https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/glslang.rb
==> Dependencies
Build: cmake ✘
==> Options
--HEAD
	Install HEAD version
==> Analytics
install: 1,147 (30 days), 1,770 (90 days), 2,664 (365 days)
install_on_request: 383 (30 days), 696 (90 days), 1,537 (365 days)
build_error: 0 (30 days)

$  brew install glslang
==> Downloading https://homebrew.bintray.com/bottles/glslang-7.10.2984.mojave.bo
######################################################################## 100.0%
==> Pouring glslang-7.10.2984.mojave.bottle.tar.gz
?  /usr/local/Cellar/glslang/7.10.2984: 58 files, 6.7MB

$ glslangValidator -v
Glslang Version: 7.10.2984
ESSL Version: OpenGL ES GLSL 3.20 glslang Khronos. 10.2984
GLSL Version: 4.60 glslang Khronos. 10.2984
SPIR-V Version 0x00010300, Revision 1
GLSL.std.450 Version 100, Revision 1
Khronos Tool ID 8
SPIR-V Generator Version 7
GL_KHR_vulkan_glsl version 100
ARB_GL_gl_spirv version 100

但是,需要注意的是,使用HomeBrew安装的版本,缺少部分功能,如果使用"-Os"(代码大小优化)参数的时候,会报告错误,如下:

$ glslangValidator -V -Os
glslangValidator: Error -Os not available; optimizer not linked (use -h for usage)

这是由于代码大小优化部分需要spirv-tools执行,然而HomeBrew编译的版本没有关联spirv-tools导致安装的程序没办法使用这个功能。

如果需要这部分功能,我们只能手动编译安装:

# 移除brew安装的版本
$ brew remove glslang

# 编译安装 glslang
$ git clone https://github.com/KhronosGroup/glslang.git

$ cd glslang

# 目前(2018.12.17)的正式版,最稳定的版本,试过最新的版本,编译部分代码存在问题
$ git checkout 7.10.2984

# 下载 spirv-tools 部分的功能代码
$ python update_glslang_sources.py 

$ mkdir build

$ cd build

$ cmake ..

$ make

$ sudo make install

继续阅读macOS Mojave(10.14.1)安装Vulkan依赖的工具链SPIR-V Toolchain

解决Android Studio 3.2.1中NDK编译代码时候出现警告": warning: conflicts with previous declaration here [-Wattributes]"

在使用Android Studio 3.2.1 结合 NDK r16/r18编译代码时候出现如下警告:

<built-in>: In function 'float abs(float)':
<built-in>: warning: conflicts with previous declaration here [-Wattributes]

关键是出现警告的代码文件中并不一定存在abs函数的调用。

这个警告产生的条件是在编译器中指定了STL,并且指定编译器为GCC,调用的源代码文件中恰好有STL的代码。

类似如下:

externalNativeBuild {
    cmake {
        cppFlags "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=gcc", "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static"
        abiFilters 'armeabi-v7a'
    }
}

原因在于新版本的NDK r16/r18中,对于GCC部分的适配已经不是非常完善了,已经逐步迁移到CLANG(LLVM)了。导致STL进行编译的时候,会出现一些警告信息。这个警告信息是STL库的警告信息,跟我们自己的代码没有关系。

只需要指定 "-DANDROID_TOOLCHAIN=clang" 即可解决这个问题。

参考链接


NDK r13, -fexceptions -Wall --> warning: conflicts with previous declaration

解决git clone --recursive部分失败后继续检出代码

在使用如下命令检出Vulkan的时候,发生失败,Vulkan的代码已经成功检出,但是子模块没有完成

$ git clone --recursive https://github.com/SaschaWillems/Vulkan.git

提示的出错信息如下:

warning: 克隆成功,但是检出失败。
您可以通过 'git status' 检查哪些已被检出,然后使用命令
'git checkout -f HEAD' 重试

可以使用如下命令继续检出子模块:

$ git submodule update --init --recursive --progress

Android Studio 3.2.1解决错误信息"No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android"

在用Android Studio 3.2.1导入以前的项目,进行编译的时候,报告如下错误信息:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

CONFIGURE FAILED in 5s
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

这个错误信息的原因是从NDK r17版本开始,已经不支持"armeabi、mips、mips64"这三种ABI格式了,而当前机器上安装的NDK版本是NDK r17之后的版本。

不过这个提示很能迷惑人,会让人误以为自己的build.gradle中配置了MIPSABI。实际上根本没有配置,是低版本的构建工具自己在默认构建MIPS格式,而又找不到对应的工具链。

解决方法很简单,要么使用低于NDK r17NDK版本,要么修改主工程的build.gradle,找到如下

// Top-level build file where you can add configuration options common to all sub-projects/modules.
configure(allprojects) {
    buildscript {
        repositories {
		    google()
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:3.0.0'
        }
    }

    repositories {
          jcenter()
    }
}

将其中的

classpath 'com.android.tools.build:gradle:3.0.0'

修改成

classpath 'com.android.tools.build:gradle:3.2.1'

高版本的构建工具,才能适配高版本的NDK

参考链接


Android Studio 3.2.1解决错误信息"ABIs [armeabi] are not supported for platform. Supported ABIs are [arm64-v8a, armeabi-v7a, x86, x86_64]."

在用Android Studio 3.2.1导入以前的项目,进行编译的时候,报告如下错误信息:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> ABIs [armeabi] are not supported for platform. Supported ABIs are [arm64-v8a, armeabi-v7a, x86, x86_64].

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s

问题发生的原因在于以前的代码在build.gradle中指定了abiFilters 'armeabi',但是从NDK r17版本开始,已经不支持"armeabi、mips、mips64"这三种ABI了。

虽然可以简单的修改成abiFilters 'armeabi-v7a',来解决问题,但是我们更希望能有一个办法,在老版本的支持abiFilters 'armeabi'NDK上继续使用abiFilters 'armeabi'进行编译,用来兼容老设备。而在只支持abiFilters 'armeabi-v7a'的设备上,我们使用abiFilters 'armeabi-v7a'保证能编译通过。

我们通过执行NDK目录下的ndk-which输出的支持的ABI列表的方式获取当前的NDK是否支持abiFilters 'armeabi',如果不支持,我们就设置为abiFilters 'armeabi-v7a'

继续阅读Android Studio 3.2.1解决错误信息"ABIs [armeabi] are not supported for platform. Supported ABIs are [arm64-v8a, armeabi-v7a, x86, x86_64]."

Android Studio 3.2.1在build.gradle中输出自定义日志&查看构建日志

在使用Android Studio开发Android项目的时候,我们有时候需要在build.gradle中增加一部分日志,来分析编译执行情况。

早期版本只能使用logger对象输出内容,如下:

logger.quiet('An info log message which is always logged.')
logger.error('An error log message.')
logger.warn('A warning log message.')
logger.lifecycle('A lifecycle info log message.')
logger.info('An info log message.')
logger.debug('A debug log message.')
logger.trace('A trace log message.')

目前最新的gradle 4.6版本已经支持println函数输出日志,如下:

println 'A message which is logged at QUIET level'

只是,目前的Android Studio 3.2.1版本中,默认情况下,输出信息被简化了,导致我们找不到添加的输出内容。

只需要点击Build选项卡中的Toggle view选项,就可以看到我们的输出了。

具体操作如下图:
继续阅读Android Studio 3.2.1在build.gradle中输出自定义日志&查看构建日志

解决Android Studio 3.2.1版本在编译Vulkan时报告错误"Could not find com.android.tools.build:aapt2:3.2.1-4818971"

目前的最新Android Studio 3.2.1版本在编译Vulkan时报告错误"Could not find com.android.tools.build:aapt2:3.2.1-4818971",详细错误信息如下:

org.gradle.api.UncheckedIOException: Failed to capture snapshot of input files for task ':examples/:radialblur:mergeDebugResources' property 'aapt2FromMaven' during up-to-date check.
	at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.snapshotTaskFiles(CacheBackedTaskHistoryRepository.java:331)
	at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.createExecution(CacheBackedTaskHistoryRepository.java:151)
	at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.access$100(CacheBackedTaskHistoryRepository.java:61)
	at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository$1.getCurrentExecution(CacheBackedTaskHistoryRepository.java:111)
	at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.getStates(DefaultTaskArtifactStateRepository.java:208)
	at org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository$TaskArtifactStateImpl.isUpToDate(DefaultTaskArtifactStateRepository.java:93)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:50)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
	at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:256)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:745)
Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':examples/:radialblur:_internal_aapt2_binary'.
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:944)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1600(DefaultConfiguration.java:120)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:918)
	at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:68)
	at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter$FileCollectionVisitorImpl.visitCollection(AbstractFileCollectionSnapshotter.java:72)
	at org.gradle.api.internal.file.AbstractFileCollection.visitRootElements(AbstractFileCollection.java:234)
	at org.gradle.api.internal.file.CompositeFileCollection.visitRootElements(CompositeFileCollection.java:185)
	at org.gradle.api.internal.changedetection.state.AbstractFileCollectionSnapshotter.snapshot(AbstractFileCollectionSnapshotter.java:55)
	at org.gradle.api.internal.changedetection.state.DefaultGenericFileCollectionSnapshotter.snapshot(DefaultGenericFileCollectionSnapshotter.java:38)
	at org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository.snapshotTaskFiles(CacheBackedTaskHistoryRepository.java:329)
	... 36 more
Caused by: org.gradle.internal.resolve.ModuleVersionNotFoundException: Could not find com.android.tools.build:aapt2:3.2.1-4818971.
Searched in the following locations:
    file:/Users/user/Library/Android/sdk/extras/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971.pom
    file:/Users/user/Library/Android/sdk/extras/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971-osx.jar
    file:/Users/user/Library/Android/sdk/extras/google/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971.pom
    file:/Users/user/Library/Android/sdk/extras/google/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971-osx.jar
    file:/Users/user/Library/Android/sdk/extras/android/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971.pom
    file:/Users/user/Library/Android/sdk/extras/android/m2repository/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971-osx.jar
    https://jcenter.bintray.com/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971.pom
    https://jcenter.bintray.com/com/android/tools/build/aapt2/3.2.1-4818971/aapt2-3.2.1-4818971-osx.jar
Required by:
    project :examples/:radialblur
	at org.gradle.internal.resolve.result.DefaultBuildableComponentResolveResult.notFound(DefaultBuildableComponentResolveResult.java:38)
	at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.resolveModule(RepositoryChainComponentMetaDataResolver.java:108)
	at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.resolve(RepositoryChainComponentMetaDataResolver.java:63)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.ComponentResolversChain$ComponentMetaDataResolverChain.resolve(ComponentResolversChain.java:93)
	at org.gradle.api.internal.artifacts.ivyservice.clientmodule.ClientModuleResolver.resolve(ClientModuleResolver.java:60)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.ComponentState.resolve(ComponentState.java:163)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.ComponentState.getMetaData(ComponentState.java:174)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.calculateTargetConfigurations(EdgeState.java:137)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.attachToTargetConfigurations(EdgeState.java:108)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.attachToTargetRevisionsSerially(DependencyGraphBuilder.java:236)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolveEdges(DependencyGraphBuilder.java:226)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.traverseGraph(DependencyGraphBuilder.java:140)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:111)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver.resolve(DefaultArtifactDependencyResolver.java:92)
	at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolveGraph(DefaultConfigurationResolver.java:146)
	at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolveGraph(ShortCircuitEmptyConfigurationResolver.java:73)
	at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolveGraph(ErrorHandlingConfigurationResolver.java:66)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$4.run(DefaultConfiguration.java:494)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveGraphIfRequired(DefaultConfiguration.java:485)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveToStateOrLater(DefaultConfiguration.java:470)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1700(DefaultConfiguration.java:120)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getSelectedArtifacts(DefaultConfiguration.java:927)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:915)
	... 43 more

导致问题的原因为源代码根目录下的build.gradle中缺少对于google源服务器的配置(话说,貌似以前版本的都在jcenter中可以找到,最新版本的,好像没有上传到jcenter服务器了,估计是google的商业策略了,在此不多做评述)

打开该文件里面的内容显示如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

解决方法为在allprojects字段中增加google()源服务器。

修改后的配置变更如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

参考链接


Build errors after Android Studio 3.2.1 upgrade

解决ubuntu 16.04下更改MySQL的数据库位置

ubuntu 16.04下使用APT安装的MySQL的数据库,目录同时接受apparmor的管理,因此在修改数据库目录的时候,需要同步更新apparmor的配置文件。如果只是迁移数据库的话

$ sudo service mysql stop

$ sudo mv /var/lib/mysql /data/

$ sudo ln -s /data/mysql /var/lib/mysql

$ sudo cp /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/usr.sbin.mysqld.bak

# 增加数据库的访问目录权限,增加如下目录的权限
#  /data/mysql/ r,
#  /data/mysql/** rw,

$ sudo sed -i "s/^[ \t]*\/var\/lib\/mysql\/\*\* rw,/  \/var\/lib\/mysql\/** rw,\n  \/data\/mysql r,\n  \/data\/mysql\/** rwk,/g" /etc/apparmor.d/usr.sbin.mysqld

# 检查完成无误之后,需要删除备份的 usr.sbin.mysqld.bak ,老版本的 apparmor 不会解析备份的文件/或者解析顺序变更了,但是新版本的会解析,导致出现两个不同的配置同时存在,引起异常
$ sudo rm -rf /etc/apparmor.d/usr.sbin.mysqld.bak

$ sudo service apparmor restart

$ sudo service mysql start

对于日志文件一起迁移的情况

$ sudo service tomcat7 stop

$ sudo service denyhosts stop

$ sudo service php7.0-fpm stop

$ sudo service apache2 stop

$ sudo service mysql stop

$ sudo service nginx stop

$ sudo service apparmor stop

$ sudo mv /var/log /data/

$ sudo ln -s /data/log /var/log

# 配置日志文件的访问目录权限,增加如下目录的权限
#  /data/log/mysql.err rw,
#  /data/log/mysql.log rw,
#  /data/log/mysql/ r,
#  /data/log/mysql/** rw,

$ sudo sed -i "s/^[ \t]*\/var\/log\/mysql\/\*\* rw,/  \/var\/log\/mysql\/** rw,\n\n  \/data\/log\/mysql.err rw,\n  \/data\/log\/mysql.log rw,\n  \/data\/log\/mysql\/ r,\n  \/data\/log\/mysql\/** rw,/g" /etc/apparmor.d/usr.sbin.mysqld

# 逐个启动服务,不如直接重启系统
$ sudo reboot

如果依旧启动失败,并且 `MySQL` 是从低版本升级上来的,并且目前正在使用的版本大于或者等于 `MySQL 5.7` ,执行 `journalctl -xe` 观察到类似如下内容:

-- Unit mysql.service has begun starting up.
Aug 20 10:16:50 AY130422143404983ad9 audit[8762]: AVC apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/proc/8762/status" pid=8762 comm="mysqld" requested_mask="r" denied_mask=
Aug 20 10:16:50 AY130422143404983ad9 kernel: audit_printk_skb: 21 callbacks suppressed
Aug 20 10:16:50 AY130422143404983ad9 kernel: audit: type=1400 audit(1566267410.233:325): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/proc/8762/status" pid=8762 comm="mysq
Aug 20 10:16:50 AY130422143404983ad9 audit[8762]: AVC apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/sys/devices/system/node/" pid=8762 comm="mysqld" requested_mask="r" deni
Aug 20 10:16:50 AY130422143404983ad9 audit[8762]: AVC apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/proc/8762/status" pid=8762 comm="mysqld" requested_mask="r" denied_mask=
Aug 20 10:16:50 AY130422143404983ad9 kernel: audit: type=1400 audit(1566267410.237:326): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/sys/devices/system/node/" pid=8762 co
Aug 20 10:16:50 AY130422143404983ad9 kernel: audit: type=1400 audit(1566267410.237:327): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/proc/8762/status" pid=8762 comm="mysq
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.244672Z 0 [Warning] Changed limits: max_open_files: 1024 (requested 5000)
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.244721Z 0 [Warning] Changed limits: table_open_cache: 431 (requested 2000)
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.418600Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.418629Z 0 [Warning] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict 
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.420618Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.27-0ubuntu0.16.04.1-log) starting as process 8762 ...
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.422604Z 0 [ERROR] Could not open file '/var/log/mysql/error.log' for error logging: Permission denied
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.423358Z 0 [ERROR] Aborting
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.423499Z 0 [Note] Binlog end
Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.423685Z 0 [Note] /usr/sbin/mysqld: Shutdown complete
Aug 20 10:16:50 AY130422143404983ad9 systemd[1]: mysql.service: Main process exited, code=exited, status=1/FAILURE

那么,此时的`MySQL`的 `apparmor` 配置文件可能还没有更新,这个时候,我们需要手工在`/etc/apparmor.d/usr.sbin.mysqld` 增加几个文件目录的权限,如下:

/proc/*/status r,
/sys/devices/system/node/ r,
/sys/devices/system/node/node0/meminfo r,

另外,注意到我这边出现

Aug 20 10:16:50 AY130422143404983ad9 mysqld[8762]: 2019-08-20T02:16:50.422604Z 0 [ERROR] Could not open file '/var/log/mysql/error.log' for error logging: Permission denied

此时,如果检查目录权限,出现如下现象:

$ ls -la  /var/log/mysql/
total 256260
dr--r-s---   2 mysql adm        4096 Aug 20 10:04 .
drwxrwxr-x+ 21 root  syslog     4096 Aug 20 06:25 ..
-rw-r--r--   1 mysql adm           0 Aug 20 10:04 error.log
-r--r-x---+  1 mysql adm        2982 Aug 20 06:25 error.log.1
-r--r-x---+  1 mysql adm        3195 Aug 19 01:52 error.log.2.gz
-r--r-x---+  1 mysql adm          20 Aug 17 06:25 error.log.3.gz
-r--r-x---+  1 mysql adm          20 Aug 16 06:25 error.log.4.gz
-r--r-x---+  1 mysql adm          20 Aug 15 06:25 error.log.5.gz
-r--r-x---+  1 mysql adm          20 Aug 14 06:25 error.log.6.gz
-r--r-x---+  1 mysql adm          20 Aug 13 06:25 error.log.7.gz
-r--r-x---+  1 mysql adm          20 Aug 12 06:25 error.log.8.gz
-r--r-x---+  1 mysql adm    11235835 Aug 10 06:25 mysql-bin.000637
-r--r-x---+  1 mysql adm     9529581 Aug 11 06:25 mysql-bin.000638
-r--r-x---+  1 mysql adm     8299217 Aug 12 06:25 mysql-bin.000639
-r--r-x---+  1 mysql adm    15319155 Aug 13 06:25 mysql-bin.000640
-r--r-x---+  1 mysql adm    15816427 Aug 14 06:25 mysql-bin.000641
-r--r-x---+  1 mysql adm    47746113 Aug 15 06:25 mysql-bin.000642
-r--r-x---+  1 mysql adm    29508705 Aug 16 06:25 mysql-bin.000643
-r--r-x---+  1 mysql adm    29720349 Aug 17 06:25 mysql-bin.000644
-r--r-x---+  1 mysql adm    34429847 Aug 18 06:25 mysql-bin.000645
-r--r-x---+  1 mysql adm    10252663 Aug 18 19:10 mysql-bin.000646
-r--r-x---+  1 mysql adm     3971401 Aug 19 01:51 mysql-bin.000647
-r--r-x---+  1 mysql adm     1799987 Aug 19 06:25 mysql-bin.000648
-r--r-x---+  1 mysql adm    44653600 Aug 20 06:25 mysql-bin.000649
-r--r-x---+  1 mysql adm         416 Aug 19 06:25 mysql-bin.index

那么需要变更用户的所有者,早期版本支持所有者为 `adm` 用户组,新版本需要 `mysql` ,我们执行如下命令:

$ sudo chown -R mysql:mysql /var/log/mysql*

$ sudo service mysql restart

参考链接