{"action":"opened","issue":{"url":"https://api.github.com/repos/RamboWANG/rambo/issues/2","repository_url":"https://api.github.com/repos/RamboWANG/rambo","labels_url":"https://api.github.com/repos/RamboWANG/rambo/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/RamboWANG/rambo/issues/2/comments","events_url":"https://api.github.com/repos/RamboWANG/rambo/issues/2/events","html_url":"https://github.com/RamboWANG/rambo/issues/2","id":141597961,"number":2,"title":" 谈一谈ps-lite的测试代码的运行命令","user":{"login":"RamboWANG","id":4134584,"avatar_url":"https://avatars.githubusercontent.com/u/4134584?v=3","gravatar_id":"","url":"https://api.github.com/users/RamboWANG","html_url":"https://github.com/RamboWANG","followers_url":"https://api.github.com/users/RamboWANG/followers","following_url":"https://api.github.com/users/RamboWANG/following{/other_user}","gists_url":"https://api.github.com/users/RamboWANG/gists{/gist_id}","starred_url":"https://api.github.com/users/RamboWANG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RamboWANG/subscriptions","organizations_url":"https://api.github.com/users/RamboWANG/orgs","repos_url":"https://api.github.com/users/RamboWANG/repos","events_url":"https://api.github.com/users/RamboWANG/events{/privacy}","received_events_url":"https://api.github.com/users/RamboWANG/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-03-17T14:25:29Z","updated_at":"2016-03-17T14:25:29Z","closed_at":null,"body":"Ps-lite是一款轻量级的参数服务器。ps-lite在运行时会依赖于zeromq以及protobuf来作为传输协议以及消息队列。目前使用的版本为: `protobuf-2.5.0`以及`zeromq-4.1.2`。ps-lite的源码包中，作者提供了一些简单的测试程序。下面，我们基于这些测试程序来谈一下ps-lite如何使用。\r\n\r\n在构建ps-lite的测试程序时，需要在bash中运行如下的编译命令:\r\n\r\n```bash\r\nmake test\r\n```\r\n\r\n编译命令执行完后，会在test目录中生成如下几个文件:\r\n\r\n-  **test_connection**: 用来测试于参数服务器的连接，代码非常简单仅调用了`ps::start()`;\r\n-  **test_simple_app**:  简单的一个*app*应用.\r\n- **test_kv_app**: 一个*key-value*的参数服务器应用;\r\n\r\n\r\n在tests包中的ReadMe文档中，给出了运行测试的命令:\r\n\r\n```bash\r\nfind test_* -type f -executable -exec ./repeat.sh 4 ./local.sh 2 2 ./{} \\;\r\n```\r\n\r\n会得到如下的输出:\r\n\r\n```bash\r\nrepeat 0: ./local.sh 2 2 ./test_connection\r\nrepeat 1: ./local.sh 2 2 ./test_connection\r\nrepeat 2: ./local.sh 2 2 ./test_connection\r\nrepeat 3: ./local.sh 2 2 ./test_connection\r\nrepeat 0: ./local.sh 2 2 ./test_kv_app\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\nrepeat 1: ./local.sh 2 2 ./test_kv_app\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\nrepeat 2: ./local.sh 2 2 ./test_kv_app\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\n[18:42:56] tests/test_kv_app.cc:47: error: 0\r\nrepeat 3: ./local.sh 2 2 ./test_kv_app\r\n[18:42:57] tests/test_kv_app.cc:47: error: 0\r\n[18:42:57] tests/test_kv_app.cc:47: error: 0\r\nrepeat 0: ./local.sh 2 2 ./test_simple_app\r\nrepeat 1: ./local.sh 2 2 ./test_simple_app\r\nrepeat 2: ./local.sh 2 2 ./test_simple_app\r\nrepeat 3: ./local.sh 2 2 ./test_simple_app\r\n```\r\n\r\n下面，我们分别来解释测试的命令和相应的测试程序。\r\n\r\n测试命令: `find test_*  ......\r\n--------------------------------------------------\r\n\r\n完整的命令行为: \r\n\r\n```bash\r\nfind test_* -type f -executable -exec ./repeat.sh 4 ./local.sh 2 2 ./{} \\;\r\n```\r\n\r\n其中，\r\n\r\n- `find`是一个常用的shell命令，用来找到满足后续正则表达式的文件。这里要找到的是以`test_`打头的文件。在ps_lite中，所有已`test_`打头的文件均为测试程序。\r\n- `-type f`是`find`命令中的一个常用的参数，表明所需寻找文件的类型。`f`代表的是正规的文件(regular file).\r\n- `-executable`是`find`中的另一个常用的参数。该参数表明，要找的文件是可执行文件。如果不带该参数，则源文件`test_kv_app.cc`等也会被找到。\r\n- `-exec` 在这条命令脚本中占有非常重要的位置。我们将这个参数的详细说明文档和解释详细给出。\r\n> > This  variant  of the -exec action runs the specified command on  the selected files, but the command line is built  by  appending  each  selected file name at the end; the total number of invocations of the command will  be  much  less  than  the  number  of              matched  files.   The command line is built in much the same way that xargs builds its command lines.  Only one instance of  '{}' is  allowed  within the command.  The command is executed in the starting directory.\r\n> > 这个参数主要用来在`find`命令所找到的文件上执行给定的命令。所要执行的命令行会将找到的文件作为命令行参数加到末尾; 命令的调用次数要小于所匹配的文件次数。命令行的构建方式与`xargs`的命令行构建方式相同。在命令行中仅仅可以使用一次'{}'作为参数来代表找到的文件。命令在开始目录中执行。\r\n\r\n- `./repeat.sh 4 ./local.sh 2 2 ./{} \\;`为要执行的命令，其中'{}'代表找到的文件；\r\n\r\n\r\n脚本解释: repeat.sh\r\n----------------------------------\r\n\r\n脚本文件`repeat.sh`的内容相对简单，只是需要注意其中的一些通配符的使用。`repeat.sh`的脚本内容如下:\r\n\r\n```bash\r\nif [ $# -lt 2 ]; then\r\n    echo \"usage: $0 num_repeats bin [args...]\"\r\n    exit -1;\r\nfi\r\nnp=$1\r\nshift\r\n\r\nfor ((i=0; i<${np}; ++i)); do\r\n    echo \"repeat $i: $@\"\r\n    $@\r\n    if [ $? != 0 ]; then\r\n        break\r\n    fi\r\n```\r\n需要注意的地方如下:\r\n- `$0`位程序名，`$1`为程序的第一个参数，总共可带9个;\r\n- `$@ $# $?`: `$@ $*`为bash的所有参数,区别在于`$#`将所有参数连成一个字符串,`$@`是多个字符串; `$#`为参数的个数; `$?`为程序运行的返回值; 另外，可以推理之，将`$@`和`$#`用双引号引住，所返回的值不同，前者只有一对引号，后者有多对引号;\r\n- `shift`将参数列表左移，舍弃前面的参数列表, 例如, `shift 3`将`$4`作为第一个参数，舍弃前面3个.\r\n\r\n脚本解释: local.sh\r\n-------------------------------\r\n脚本比较简单，不细讲，需要注意里面需要export出来的环境变量.\r\n\r\n- `DMLC_NUM_SERVER=$1`: 服务端的个数;\r\n- `DMLC_NUM_WORKER=$1`:worker的个数;\r\n- `DMLC_PS_ROOT_URI='127.0.0.1'`: ROOT_URI的IP值;\r\n- `DMLC_PS_ROOT_PORT=8000`: ROOT的端口;\r\n- `DMLC_ROLE='scheduler'`:DMLC的角色;\r\n- `HEAPPROFILE=./S${i}`: "}}