用badblocks检测硬盘坏道

硬盘是一个损耗设备,当使用一段时间后可能会出现坏道等物理故障。电脑硬盘出现坏道后,如果不及时更换或进行技术处理,坏道就会越来越多,并会造成频繁死机和数据丢失。最好的处理方式是更换磁盘,但在临时的情况下,应及时屏蔽坏道部分的扇区,不要触动它们。badblocks就是一个检查坏道位置的工具。

一、命令参数
badblocks使用格式为:

badblocks [ -svwnf ] [ -b block-size ] [ -c blocks_at_once ] [ -i input_file ] [ -o output_file ] [ -p num_passes ] [ -t test_pattern ] device [ last-block ] [ start-block ]

参数含义是:

-b blocksize
指定磁盘的区块大小,单位为字节,默认值为“block 4K ”(4K/block)
-c blocksize
每个区块检查的次数,默认是16次
-f
强制在一个已经挂载的设备上执行读写或非破坏性的写测试操作
(我们建议先umount设备,然后再进行坏道检测。仅当/etc/mtab出现误报设备挂载错误的时候可以使用该选项)
-i file
跳过已经显示在file文件中的坏道,而不进行检测(可以避免重复检测)
-o file
把检测结果输出到file文件
-p number
重复搜寻设备,直到在指定通过次数内都没有找到新的坏块位置,默认次数为0
-s
在检查时显示进度
-t pattern
通过按指定的模式读写来检测区块。你可以指定一个0到ULONG_MAX-1的十进制正值,或使用random(随机)。
如果你指定多个模式,badblocks将使用第一个模式检测所有的区块,然后再使用下一个模式检测所有的区块。
Read-only方式仅接受一个模式,它不能接受random模式的。
-v
执行时显示详细的信息
-w
对每个区块都先写入,然后再从它读取信息
[device]
指定要检查的磁盘装置。
[last-block]
指定磁盘装置的区块总数。
[start-block]
指定要从哪个区块开始检查

二、示例
badblocks以4096的一个block,每一个block检查16次,将结果输出到“hda-badblocks-list”文件里

# badblocks -b 4096 -c 16 /dev/hda1 -o hda-badblocks-list

"hda-badblocks-list”是个文本文件,内容如下:
引用

# cat hda-badblocks-list
51249
51250
51251
51253
51254
……
61245
……

可以针对可疑的区块多做几次操作。下面,badblocks以4096字节为一个“block”,每一个“block”检查1次, 将结果输出到“hda-badblocks-list.1”文件中,由第51000 block开始,到63000 block结束

# badblocks -b 4096 -c 1 /dev/hda1 -o hda-badblocks-list.1 63000 51000

这次花费的时间比较短,硬盘在指定的情况下在很短的时间就产生“嘎嘎嘎嘎”的响声。由于检查条件的不同,其输出的结果也不完全是相同的。重复几次同样的操作,因条件多少都有些不同,所以结果也有所不同。进行多次操作后,直到产生最后的hda-badblock-list.final文件。

三、其他
1、fsck使用badblocks的信息
badblocks只会在日志文件中标记出坏道的信息,但若希望在检测磁盘时也能跳过这些坏块不检测,可以使用fsck的-l参数:

# fsck.ext3 -l /tmp/hda-badblock-list.final /dev/hda1

2、在创建文件系统前检测坏道
badblocks可以随e2fsck和mke2fs的-c删除一起运行(对ext3文件系统也一样),在创建文件系统前就先检测坏道信息:

# mkfs.ext3 -c /dev/hda1

代码表示使用-c在创建文件系统前检查坏道的硬盘。
这个操作已经很清楚地告知我们可以采用“mkfs.ext3 -c”选项用“read-only”方式检查硬盘。这个命令会在格式化硬盘时检查硬盘,并标出错误的硬盘“block”。用这个方法格式化硬盘,需要有相当大的耐心,因为命令运行后,会一个个用读的方式检查硬盘。

Android Studio 1.2 开发JNI工程

  • 添加native接口

注意写好native接口和System.loadLibrary()即可了,并无特别之处。

public class MainActivity extends Activity{
    static {
        System.loadLibrary("JniTest");
    }
   
    public native String getStringFromNative();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView txtView = (TextView) findViewById(R.id.txt);
        txtView.setText(getStringFromNative());
    }
}
  • 执行Build->Make Project

20141215184150750
这一步骤执行一下,验证工程中并无其它错误,并对工程进行了编译,生成了.class文件.
.class文件的生成路径是在 app_path/build/intermediates/classes/debug下的.如下图:20141215184245654

  • javah生成c头文件

点击"View->Tool Windows->Terminal",即在Studio中进行终端命令行工具.执行如下命令生成c语言头文件。
这里需要注意的是要进入 \app\src\main的目录下执行javah命令,为的是生成的 .h 文件同样是在\app\src\main路径下,可以在Studio的工程结构中直接看到。

$ cd app/src/main

$ javah -d jni -classpath %Android_SDK_Home%\platforms
\android-21\android.jar;..\..\build\intermediates\classes\debug lab.sodino.jnitest.MainActivity

最后的生成结果:20141215184427109

  • 编辑c文件

在main.c文件中实现头文件中的方法,具体功能为直接return回一个String,并且使用android_log打印出相关日志。
代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h>

#ifndef LOG_TAG
#define LOG_TAG "ANDROID_LAB"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif

/* Header for class lab_sodino_jnitest_MainActivity */

#ifndef _Included_lab_sodino_jnitest_MainActivity
#define _Included_lab_sodino_jnitest_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: lab_sodino_jnitest_MainActivity
 * Method: getStringFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_lab_sodino_jnitest_MainActivity_getStringFromNative
  (JNIEnv * env, jobject jObj){
      LOGE("log string from ndk.");
      return (*env)->NewStringUTF(env,"Hello From JNI!");
  }

#ifdef __cplusplus
}
#endif
#endif
    •  配置NDK

20141215184556957

  • Jni目录下手工创建Application.mk

里面内容如下:

APP_PLATFORM := android-21
  • Jni目录下手工创建Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE:= JniTest

LOCAL_LDLIBS+= -L$(SYSROOT)/usr/lib -llog

LOCAL_SRC_FILES := main.c 
					
include $(BUILD_SHARED_LIBRARY)

再执行"Build->Rebuild Project",就可以编译出so文件了.

如果

Android_studio_jni

跟我的代码布局类似,增加了一个include目录,里面包含引用的第三方头文件,那么就比较折腾,因为编译的时候会报告找不到头文件,而通过设置

LOCAL_C_INCLUDES += $(LOCAL_PATH)/include/

是可以通过命令行编译通过的,但是却不能在Gradle中编译通过。

这种情况下,需要放弃Android Studio 自带的配置,修改app目录下的“build.gradle”

原始内容如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "mobibrw.longsky.com.sctpclient"
        minSdkVersion 21
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

修改后的内容如下:

import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "mobibrw.longsky.com.sctpclient"
        minSdkVersion 21
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir './src/main/libs'
    }

    task ndkBuild(type:Exec) {
        def Properties localProps = new Properties()
        localProps.load(new FileInputStream("local.properties"))
        def ndk_dir = localProps['ndk.dir']
        def ndk_build_cmd = "$ndk_dir/ndk-build"
        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            ndk_build_cmd = "$ndk_dir/ndk-build.cmd"
        }
        commandLine ndk_build_cmd, '-j', Runtime.runtime.availableProcessors(),"NDK_OUT=$buildDir/native/obj","NDK_PROJECT_PATH=./src/main"
    }

    tasks.withType(JavaCompile) {
        compileTask->compileTask.dependsOn ndkBuild
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

参考 http://blog.csdn.net/sodino/article/details/41946607

Source Insight添加.cc文件

在导入代码时, 发现Souce Insight只导入了.h文件,.cc文件没有导入. Source Insight对C++项目的导入,其文件过滤没有包含*.cc文件, 需要自己手动设置导入:

  1. options->document options->在document type中选择C++ Source->在右边的File Filter里加上*.cc文件
  2. 重新添加项目文件: project->Add and Remove Project files

具体操作如图所示

1.选择“Document Options”
Source_Insight_Document_Options

2.选择 “Document Type”Source_Insight_Document_Type

3.选择“C++”

Source_Insight_Document_Type_Sel

4.增加 “*.CC”

Source_Insight_C_Plus_Add_CC

Android Studio *.jar 与 *.aar 的生成与*.aar导入项目方法

Android Studio的一个好处在于Android函数库包格式“aar”格式。以前,Android函数库通常需要被导入到IDE以此将App需要的资源加入编译。但是现在的Android函数库可以被直接包含,与“jar”文件被Java项目包含的方式类似。这项功能虽然出现已久,但确实非常受欢迎。

  • Android Studio新建一个Library

1.点击“New Module”

Android_Studio_New_Module_Menu

2.选中新建“Android Library”Android_Studio_New_Module_Libary_Wards

3.根据向导一步一步继续下去就可以了。

  • 简单介绍

在Android Studio中对一个自己库进行生成操作时将会同时生成*.jar与*.aar文件。

分别存储位置:

*.jar:库 /build/intermediates/bundles/debug(release)/classes.jar

*.aar:库 /build/outputs/aar/libraryname.aar

两者区别:

*.jar: 只包含了class文件与清单文件 ,不包含资源文件,如图片等所有res中的文件。

*.aar: 包含所有资源 ,class以及res资源文件全部包含

如果你只是一个简单的类库那么使用生成的*.jar文件即可;如果你的是一个UI库,包含一些自己写的控件布局文件以及字体等资源文件那么就只能使用*.aar文件。

使用方式:

*.jar:拷贝到:libs目录,eclipse直接导入即可,AndroidStudio项目中添加:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
}

重新编译一次项目既可完成加载。

*.aar:有两种方式,分别为本地加载以及网络加载,由于网络加载涉及到发布到mavenCentral托管的问题这里不做讨论;另外eclipse很久没有使用了也不做讨论;在这里给大家说一种本地加载的方式,简单快捷。

这里演示的aar文件为: “genius.aar”

第一步:拷贝到:libs目录

第二步:build.gradle 配置文件中更改为

repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
    compile(name:'genius', ext:'aar')
}

分别添加了 “repositories” 与更改了 “dependencies” ,然后重新编译一次项目就可以正常使用了。

这时打开你的项目地址 “\build\intermediates\exploded-aar\” 你会发现下面多了一个文件夹 “genius”打开后能看见里边包含了一个 “classes.jar” 文件与一些 资源文件和“R.txt”文件 。

r6BBviN

这就是Android Studio自动解析了aar文件后出现的东西。

对于比较常见的项目配置,有如下的参考,可以看到带版本号的情况,使用的aar跟jar文件还是有差别的,aar文件,最后要增加一个“@aar”的标记。

dependencies {
    androidTestCompile 'junit:junit:4.+'
    compile fileTree(dir: 'libs', include: '*.jar')
    compile 'com.github.flavienlaurent.datetimepicker:library:0.0.2'
    compile 'de.keyboardsurfer.android.widget:crouton:1.8.4@aar'
    compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0'
}

参考链接


[Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法

Crosswalk入门

Crosswalk是一款开源的WEB引擎。目前Crosswalk正式支持的移动操作系统包括Android和Tizen,在Android 4.0及以上的系统中使用Crosswalk的Web应用程序在HTML5方面可以有一致的体验,同时和系统的整合交互方面(比如启动画面、权限管理、应用切换、社交分享等等)可以做到类似原生应用。现在Crosswalk已经成为众多知名HTML5平台和应用的推荐引擎,包括Google Mobile Chrome App、Intel XDK、Famo.us和Construct2等等,未来的Cordova 4.0也计划集成Crosswalk。

下载的时候有些小迷茫,不知道应该下载哪个,入门的话,还是使用下图的稳定版本好了。
CrossViewDownload

  • 集成到应用中

1.下载zip包,然后参考 Android Studio如何Import Module 即项目依赖(针对非Gradle项目,以Crosswalk为例) 中的介绍,建立Android Studio工程,并且导入到项目中。

2.在AndroidManifest.xml中增加如下权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

使用XWalkView必须开启硬件加速,修改AndroidManifest.xml

<application 
android:name="android.app.Application"
android:label="XWalkUsers"
android:hardwareAccelerated="true">
  • 基本使用

Crosswalk中用来替代WebView的控件叫XWalkView

1.layout文件写法

<org.xwalk.core.XWalkView 
 android:id="@+id/activity_main"
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
</org.xwalk.core.XWalkView>

2.代码中使用
和其他Android的控件不同,这个类需要监听系统事件。例如:生命周期、intent、Activity result。
控件内置的Web引擎需要获取并处理这些信息。并且当XWalkView 不再需要使用的时候,在onDestroy方法中XWalkView必须显式的调用destroy方法,否则容易造成Web引擎的内存泄漏。

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import org.xwalk.core.XWalkView;

public class MainActivity extends ActionBarActivity {

    private XWalkView mXWalkView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mXWalkView = (XWalkView) findViewById(R.id.activity_main);
        mXWalkView.load("http://crosswalk-project.org/", null);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mXWalkView != null) {
            mXWalkView.pauseTimers();
            mXWalkView.onHide();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mXWalkView != null) {
            mXWalkView.resumeTimers();
            mXWalkView.onShow();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mXWalkView != null) {
            mXWalkView.onDestroy();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,Intent data) {
        if (mXWalkView != null) {
            mXWalkView.onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (mXWalkView != null) {
            mXWalkView.onNewIntent(intent);
        }
    }
}

3.loadUrl去哪了?

上面的代码中其实已经剧透了,使用load方法即可。

// url
mXWalkView.load("http://crosswalk-project.org/", null);

// this loads a file from the assets/ directory
mXWalkView.load("file:///android_asset/index.html", null);

4.WebViewClient?

对应WebView的WebViewClient,XWalkView中有XWalkResourceClient。

mXWalkView.setResourceClient(new XWalkResourceClient(mXWalkView){
	@Override
	public void onLoadFinished(XWalkView view, String url) {
		super.onLoadFinished(view, url);
	}
	@Override
	public void onLoadStarted(XWalkView view, String url) {
		super.onLoadStarted(view, url);
	}
});
  • 调用JavaScript

不像WebView一样获取setting设置setJavaScriptEnabled为true才能执行。
Crosswalk可以直接执行js。

mXWalkView.load("javascript:document.body.contentEditable=true;", null);

当然,按照Kitkat引入的方式,使用evaluateJavascript方法也是可以的。(大神们推荐)

  • JavaScript回调Java

  1. 定义js回调接口
    public class JsInterface {
        public JsInterface() {
        }
        @JavascriptInterface
        public String sayHello() {
            return "Hello World!";
        }
    }

    Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available to your JavaScript (the method must also be public). If you do not provide the annotation, the method is not accessible by your web page when running on Android 4.2 or higher.
    From developer.android.com

    备注:这里的

    @JavaScriptInterface

    所在的包是

    import org.xwalk.core.JavascriptInterface;
  2. XWalkView设置JavaScript可用且绑定对象
    //绑定
    mXWalkView.addJavascriptInterface(new JsInterface(), "NativeInterface");
  3. 调用html执行JavaScript或直接执行Javascript调用Java
    mXWalkView.load("file:///android_asset/index.html", null);

    index.html源码:

    <a href="#" onclick="clicked()">Say Hello</a> <script>
    function clicked() {
    	alert(NativeInterface.sayHello());
    }
    </script>
  • 高级使用

调试

Kitkat开始,Android提供了和Chrome联调功能。可以很方便的在Chrome中调试WebView中的代码。
Crosswalk使用Chromium内核当然也具备这个功能。
开启调试的语句如下:

// turn on debugging 
XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);

对于Crosswalk来说,这个设置是全局的。

使用动画或者设置隐藏可见注意

默认XWalkView不能使用动画,甚至setVisibility也不行。

XWalkView represents an Android view for web apps/pages. Thus most of attributes for Android view are valid for this class. Since it internally uses android.view.SurfaceView for rendering web pages by default, it can't be resized, rotated, transformed and animated due to the limitations of SurfaceView. Alternatively, if the preference key ANIMATABLE_XWALK_VIEW is set to True, XWalkView can be transformed and animated because TextureView is intentionally used to render web pages for animation support. Besides, XWalkView won't be rendered if it's invisible.

开启动画模式:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ANIMATABLE_XWALK_VIEW preference key MUST be set before XWalkView creation.
    XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true);

    setContentView(R.layout.animatable_xwview_layout);
}
@Override
public void onDestroy() {
    super.onDestroy();

    // Reset the preference for animatable XWalkView.
    XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, false);
}

由于设置也像调试一样是全局的,在onDestroy时记得关闭。

暂停JS timer

html代码

<!DOCTYPE html>
<html>
<body>

<p>A script on this page starts this clock:</p>
<p id="demo"></p>

<script>
  var myVar = setInterval(function(){ myTimer(); }, 1000);

  function myTimer()
  {
    var d = new Date();
    var t = d.toLocaleTimeString();
    document.getElementById("demo").innerHTML = t;
  }
</script>

</body>
</html>

XWalkView对应方法:

mButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mXWalkView != null) {
            if (!isPaused) {
                // Pause JS timer
                mXWalkView.pauseTimers();
                isPaused = true;
                mButton.setImageResource(android.R.drawable.ic_media_play);
            } else {
                // Resume JS timer
                mXWalkView.resumeTimers();
                isPaused = false;
                mButton.setImageResource(android.R.drawable.ic_media_pause);
            }
        }
    }
});

这也在防止内存泄漏,监听系统事件示例代码中提到过:

@Override
protected void onPause() {
   super.onPause();
   if (mXWalkView != null) {
       mXWalkView.pauseTimers();
       mXWalkView.onHide();
   }
}

@Override
protected void onResume() {
   super.onResume();
   if (mXWalkView != null) {
       mXWalkView.resumeTimers();
       mXWalkView.onShow();
   }
}

历史记录

mPrevButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // Go backward
        if (mXWalkView != null &&
                mXWalkView.getNavigationHistory().canGoBack()) {
            mXWalkView.getNavigationHistory().navigate(
                    XWalkNavigationHistory.Direction.BACKWARD, 1);
        }
        XWalkNavigationItem navigationItem = mXWalkView.getNavigationHistory().getCurrentItem();
        showNavigationItemInfo(navigationItem);
    }
});

mNextButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // Go forward
        if (mXWalkView != null &&
                mXWalkView.getNavigationHistory().canGoForward()) {
            mXWalkView.getNavigationHistory().navigate(
                    XWalkNavigationHistory.Direction.FORWARD, 1);
        }
        XWalkNavigationItem navigationItem = mXWalkView.getNavigationHistory().getCurrentItem();
        showNavigationItemInfo(navigationItem);
    }
});

private void showNavigationItemInfo(XWalkNavigationItem navigationItem){
    url = navigationItem.getUrl();// Get the url of current navigation item.
    originalUrl = navigationItem.getOriginalUrl();// Get the original url of current navigation item
    title = navigationItem.getTitle();

    text1.setText(title);
    text2.setText(url);
    text3.setText(originalUrl);
}

自动视频暂停

// The web page below will display a video.
// When home button is pressed, the activity will be in background, and the video will be paused.
mXWalkView.load("http://www.w3.org/2010/05/video/mediaevents.html", null);

loadAppFromManifest

mXWalkView.loadAppFromManifest("file:///android_asset/manifest.json", null);

manifest.json

{
  "name": "ManifestTest",
  "start_url": "index.html",
  "description": "Manifest test",
  "version": "1.0.0"
}

参考链接


ubuntu 12.04配置rsync服务

rsync,remote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息。

默认情况ubuntu安装了rsync服务,但在/etc下没有配置文件,一般情况可以copy示例文件到/etc下

  • 安装sync,xinetd
$ sudo apt-get install rsync xinetd
  • 拷贝示例配置文件到/etc目录下
$ sudo cp /usr/share/doc/rsync/examples/rsyncd.conf /etc

查看内容,可以看到如下内容

# sample rsyncd.conf configuration file

# GLOBAL OPTIONS

#motd file=/etc/motd
#log file=/var/log/rsyncd
# for pid file, do not use /var/run/rsync.pid if
# you are going to run rsync out of the init.d script.
# pid file=/var/run/rsyncd.pid
#syslog facility=daemon
#socket options=

# MODULE OPTIONS

[ftp]

 comment = public archive
 path = /var/www/pub
 use chroot = yes
# max connections=10
 lock file = /var/lock/rsyncd
# the default for read only is yes...
 read only = yes
 list = yes
 uid = nobody
 gid = nogroup
# exclude =
# exclude from =
# include =
# include from =
# auth users =
# secrets file = /etc/rsyncd.secrets
 strict modes = yes
# hosts allow =
# hosts deny =
 ignore errors = no
 ignore nonreadable = yes
 transfer logging = no
# log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
 timeout = 600
 refuse options = checksum dry-run
 dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
  • 修改同步的目录,用户名,密码,日志信息
$ sudo vim /etc/rsyncd.conf

1.修改

path = /var/www/pub

为需要同步的目录。
如果路径中存在空格,则要分两种情况处理,如果空格在路径中间,如"/nfs/Public/Shared Videos",则直接写

path = /nfs/Public/Shared Videos

如果空格在路径的最后面,如"/nfs/Public/Shared Videos ",则需要如下形式设置,注意最后面的"\ ",是一个反斜杠加空格,否则最后的空格会被忽略。

path = /nfs/Public/Shared Videos\

2.设置可以登录的用户名,密码,修改

# auth users =
# secrets file = /etc/rsyncd.secrets

auth users = user
secrets file = /etc/rsyncd.secrets

配置用户名和密码

$ sudo vim /etc/rsyncd.secrets 

  user:password

赋予权限 rsyncd.secrets的权限必须为600

$ sudo chmod 600 /etc/rsyncd.secrets

3.开启日志

#log file=/var/log/rsyncd

log file=/var/log/rsyncd

4.如果提示

rsync: change_dir "/" (in ftp) failed: Permission denied (13)

则调整

uid = nobody
gid = nogroup

uid = root
gid = root

5.对于严格要求一致性的重要的文件,去掉"refuse options"中的"checksum",这样会导致同步变慢,但是会比较安全(已经有报告说当同步时候不校验MD5会出现文件大小一致但是MD5不正确的情况),这个需要客户端在同步的时候使用 "-c" 作为参数。

 refuse options = dry-run
  • 编辑/etc/default/rsync 启动rsync作为使用xinetd的守护进程
$ sudo vim /etc/default/rsync

修改

RSYNC_ENABLE=inetd

创建 /etc/xinetd.d/rsync 通过xinetd使rsync开始工作

$ sudo vim /etc/xinetd.d/rsync

  service rsync
    {
        disable         = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon
        log_on_failure  += USERID
    }

启动/重启 xinetd

$ sudo /etc/init.d/xinetd restart
  • 测试

运行下面的命令检查,确认rsync配置成功。

$ sudo rsync user@www.mobibrw.com::ftp
  Password: 
  drwxr-xr-x        4096 2006/12/13 09:41:59 .
  drwxr-xr-x        4096 2006/11/23 18:00:03 folders
  • 从服务器同步文件
$ sudo rsync -cvazu --progress user@www.mobibrw.com::ftp /rsync
Password:
receiving incremental file list
./
...................................

c同步完成后校验文件MD5(慢,但是可靠)
v详细提示
a以archive模式操作,复制目录、符号连接
z压缩
u只进行更新,防止本地新文件被重写,注意两者机器的时钟的同步
--progress指显示进度

注意,如果需要为多个目录做独立的配置,可以参考如下配置(配置中设置了两个独立的同步目录"ftp"跟"movie"

# sample rsyncd.conf configuration file

# GLOBAL OPTIONS

#motd file=/etc/motd
log file=/var/log/rsyncd
# for pid file, do not use /var/run/rsync.pid if
# you are going to run rsync out of the init.d script.
# pid file=/var/run/rsyncd.pid
#syslog facility=daemon
#socket options=

# MODULE OPTIONS

[ftp]
 comment = public archive
 path=/nfs/MyCloud
 use chroot = yes
# max connections=10
 lock file = /var/lock/rsyncd
# the default for read only is yes...
 read only = yes
 list = yes
 uid = root
 gid = root
# exclude =
# exclude from =# hosts allow =
# hosts deny =
# include =
# include from =
 auth users = user
 secrets file = /etc/rsyncd.secrets
 strict modes = yes
# hosts allow =
# hosts deny =
 ignore errors = no
 ignore nonreadable = yes
 transfer logging = no
# log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
 timeout = 600
 refuse options = dry-run
 dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz

[movie]
 comment = public archive
 path= /nfs/Public/Shared Videos
 use chroot = yes
# max connections=10
 lock file = /var/lock/rsyncd
# the default for read only is yes...
 read only = yes
 list = yes
 uid = root
 gid = root
# exclude =
# exclude from =
# include =
# include from =
 auth users = user
 secrets file = /etc/rsyncd.secrets
 strict modes = yes
# hosts allow =
# hosts deny =
 ignore errors = no
 ignore nonreadable = yes
 transfer logging = no
# log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
 timeout = 600
 refuse options = dry-run
 dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
  • 通过计划任务定时同步

1.创建脚本文件,假定文件在/home目录

$ vim rsync_backup.sh

#!/bin/sh 
rsync -auvz --password-file=/home/rsyncd.secrets user@www.mobibrw.com::ftp /rsync

2.赋予执行权限

$ chmod +x rsync_backup.sh

3.创建密码文件,自动填写密码

$ vim /home/rsyncd.secrects

password

4.创建定时任务,每半小时自动检查备份一次

  • 编辑计划任务文件,执行日志输出到 “/var/log/cron_rsync_backup.log”
$ vim cron_rsync_backup

*/30 * * * *  /home/rsync_backup.sh > /var/log/cron_rsync_backup.log 2>&1
  •  增加计划任务
$ crontab /home/cron_rsync_backup
  •  重启计划任务,使之生效
$ /etc/init.d/cron restart
  • 检查是否已经成功增加计划
$ crontab -l

Android Studio如何Import Module 即项目依赖(针对非Gradle项目,以Crosswalk为例)

我们要写一个使用CrosswalkWebView的项目,就要依赖Crosswalk的工程,在Eclipse中存在Workspace的概念,对应到Android Studio 就变成了Module.

我们下载到的Crosswalk-WebView的工程是Eclipse建立的项目,此时项目是不能被Android Studio直接引用的,因此需要导入成Android Studio项目的一个Module。

  • 导入Module

1.选择"Import Module"菜单

选择导入Android Studio项目的一个Module
选择导入Android Studio项目的一个Module

2.选择项目的路径,并且重命名 Module Name

导入项目路径并且重命名Module的名字
导入项目路径并且重命名Module的名字

3.完成导入

导入项目的最后一步
导入项目的最后一步

4.查看导入完成后的项目中,出现了新导入的 "CrosswalkWebview",实质上是拷贝了所需要的文件到工程的目录中

导入完成后的模块,出现在工程中
导入完成后的模块,出现在工程中

  • 设置Module之间项目依赖

1.选择"Open Module Settings"
Config_Module_Settings

2.设置模块依赖Module_Depends_Setting

3.选择依赖的ModuleModule_Depends_Select

4.选中依赖的模块,点击“OK”Checked_Selected_Modules