linux study

linux查看用户列表

cat /etc/passwd 可以查看所有用户的列表
w 可以查看当前活跃的用户列表
cat /etc/group 查看用户组

cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print $1"|"$3"|"$4 }'|more

这样一来,show出来的就只是用户列表和一点点东西了~

linux定时任务的设置

为当前用户创建cron服务

1.  键入 crontab  -e 编辑crontab服务文件

      例如 文件内容如下:

     */2 * * * * /bin/sh /home/admin/jiaoben/buy/deleteFile.sh 

     保存文件并并退出

     */2 * * * * /bin/sh /home/admin/jiaoben/buy/deleteFile.sh

    */2 * * * * 通过这段字段可以设定什么时候执行脚本

      /bin/sh /home/admin/jiaoben/buy/deleteFile.sh 这一字段可以设定你要执行的脚本,这里要注意一下bin/sh 是指运行  脚本的命令  后面一段时指脚本存放的路径

2. 查看该用户下的crontab服务是否创建成功, 用 crontab  -l 命令  

3. 启动crontab服务 

      一般启动服务用  /sbin/service crond start 若是根用户的cron服务可以用 sudo service crond start, 这里还是要注意  下 不同版本linux系统启动的服务的命令也不同 ,像我的虚拟机里只需用 sudo service cron restart 即可,若是在根用下直接键入service cron start就能启动服务

4. 查看服务是否已经运行用 ps -ax | grep cron 

5. crontab命令

      cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:

        crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数  
  crontab -l //列出某个用户cron服务的详细内容
  crontab -r //删除没个用户的cron服务
  crontab -e //编辑某个用户的cron服务
  比如说root查看自己的cron设置:crontab -u root -l
  再例如,root想删除fred的cron设置:crontab -u fred -r
  在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e
  进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt
        任务调度的crond常驻命令
        crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此  

       任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工

       作便会自动执行该工作。

6. crontab命令选项:

     -u指定一个用户

     -l列出某个用户的任务计划

     -r删除某个用户的任务

     -e编辑某个用户的任务

7. cron文件语法:

      分     小时    日       月       星期     命令

      0-59   0-23   1-31   1-12     0-6     command     (取值范围,0表示周日一般一行对应一个任务)

     记住几个特殊符号的含义:

         “*”代表取值范围内的数字,
         “/”代表”每”,
         “-”代表从某个数字到某个数字,
         “,”分开几个离散的数字

8. 任务调度设置文件的写法
      可用crontab -e命令来编辑,编辑的是/var/spool/cron下对应用户的cron文件,也可以直接修改/etc/crontab文件
     具体格式如下:
      Minute Hour Day Month Dayofweek   command
      分钟     小时   天     月       天每星期       命令
     每个字段代表的含义如下:
     Minute             每个小时的第几分钟执行该任务
     Hour               每天的第几个小时执行该任务
     Day                 每月的第几天执行该任务
     Month             每年的第几个月执行该任务
     DayOfWeek     每周的第几天执行该任务
     Command       指定要执行的程序
     在这些字段里,除了“Command”是每次都必须指定的字段以外,其它字段皆为可选

    字段,可视需要决定。对于不指定的字段,要用“*”来填补其位置。
    举例如下:
    5       *       *           *     *     ls             指定每小时的第5分钟执行一次ls命令
    30     5       *           *     *     ls             指定每天的 5:30 执行ls命令
    30     7       8         *     *     ls             指定每月8号的7:30分执行ls命令
    30     5       8         6     *     ls             指定每年的6月8日5:30执行ls命令
    30     6       *           *     0     ls             指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,

    以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

   30     3     10,20     *     *     ls     每月10号及20号的3:30执行ls命令[注:“,”用来连接多个不连续的时段]

    25     8-11 *           *     *     ls       每天8-11点的第25分钟执行ls命令[注:“-”用来连接连续的时段]

    */15   *       *           *     *     ls         每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

     30   6     */10         *     *     ls       每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls 命令。 ]

     每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件

     50   7       *             *     *     root     run-parts     /etc/cron.daily   [ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]

9. 新增调度任务

     新增调度任务可用两种方法:
       1)、在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。
        2)、直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。

10. 查看调度任务
        crontab -l //列出当前的所有调度任务
        crontab -l -u jp   //列出用户jp的所有调度任务

11. 删除任务调度工作
         crontab -r   //删除所有任务调度工作

12. 任务调度执行结果的转向
       例1:每天5:30执行ls命令,并把结果输出到/jp/test文件中
            30 5 * * * ls >/jp/test 2>&1
            注:2>&1 表示执行结果及错误信息。
      编辑/etc/crontab 文件配置cron  

     cron服务每分钟不仅要读一次/var/spool/cron内的所有文件,还需要读一次 /etc/crontab,因此我们配置这个文件也能运用cron服务做一些事情。用crontab配置是针对某个用户的,而编辑/etc/crontab是针对系统的任务。此文件的文件格式是:  

  SHELL=/bin/bash  

  PATH=/sbin:/bin:/usr/sbin:/usr/bin 

  MAILTO=root //如果出现错误,或者有数据输出,数据作为邮件发给这个帐号  

  HOME=/ //使用者运行的路径,这里是根目录  
  # run-parts  

  01   *   *   *   *     root run-parts /etc/cron.hourly         //每小时执行

        /etc/cron.hourly内的脚本  

     02   4   *   *   *     root run-parts /etc/cron.daily           //每天执行/etc/cron.daily内的脚本  

       22   4   *   *   0     root run-parts /etc/cron.weekly       //每星期执行 /etc/cron.weekly内的脚本  

      42   4   1   *   *     root run-parts /etc/cron.monthly     //每月去执行/etc/cron.monthly内的脚本  
  大家注意”run-parts”这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了

    例如:

     1) 在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。

      2)直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务
          11 2 21 10 * rm -rf /mnt/fb  

原文地址:http://qa.taobao.com/?p=9189

OpenTSDB 详解

1. OpenTSDB介绍

OpenTSDB用HBase存储所有的时序(无须采样)来构建一个分布式、可伸缩的时间序列数据库。它支持秒级数据采集所有metrics,支持永久存储,可以做容量规划,并很容易的接入到现有的报警系统里。OpenTSDB可以从大规模的集群(包括集群中的网络设备、操作系统、应用程序)中获取相应的metrics并进行存储、索引以及服务,从而使得这些数据更容易让人理解,如web化、图形化等。

对于运维工程师而言,OpenTSDB可以获取基础设施和服务的实时状态信息,展示集群的各种软硬件错误,性能变化以及性能瓶颈。对于管理者而言,OpenTSDB可以衡量系统的SLA,理解复杂系统间的相互作用,展示资源消耗情况。集群的整体作业情况,可以用以辅助预算和集群资源协调。对于开发者而言,OpenTSDB可以展示集群的主要性能瓶颈,经常出现的错误,从而可以着力重点解决重要问题。

OpenTSDB使用LGPLv2.1+开源协议,目前版本为2.X。

2. 安装OpenTSDB

2.1 依赖

OpenTSDB依赖jdk和Gnuplot,Gnuplot需要提前安装,版本要求为最小4.2,最大4.4,执行以下命令安装即可:

OpenTSDB是用java编写的,但是项目构建不是用的java的方式而是使用的C、C++程序员构建项目的方式。运行时依赖:

可选的编译时依赖:

  • GWT 2.4 (ASLv2)

可选的单元测试依赖:

2.2 下载并编译源代码

首先安装必要依赖:

下载源代码,可以指定最新版本或者手动checkout

2.3 安装

  • 1. 首先安装一个单节点或者多节点集群的hbase环境,hbase版本要求为0.94
  • 2. 设置环境变量并创建opentsdb使用的表,需要设置的环境变量为COMPRESSIONHBASE_HOME,前者设置是否启用压缩,或者设置hbase home目录。如果使用压缩,则还需要安装lzo
  • 3. 执行建表语句src/create_table.sh
  • 4. 启动TSD

如果你使用的是hbase集群,则你还需要设置--zkquorum--cachedir对应的目录会产生一些临时文件,你可以设置cron定时任务进行删除。添加--auto-metric,则当新的数据被搜集时自动创建指标。

你可以将这些参数编写到配置文件中,然后通过--config指定该文件所在路径。

  • 5. 启动成功之后,你可以通过127.0.0.1:4242进行访问。

从源代码安装gnuplot、autoconf、opentsdb以及tcollector,可以参考:OpenTSDB & tcollector 安装部署(Installation and Deployment)

3. 使用向导

3.1 配置

OpenTSDB的配置参数可以在命令行指定,也可以在配置文件中指定。配置文件使用的是java的properties文件,文件中key为小写,支持逗号连接字符串但是不能有空格。所有的OpenTSDB属性都以tsdb开头,例如:

配置参数优先级:

命令行参数 > 配置文件 > 默认值

你可以在命令行中通过--config指定配置文件所在路径,如果没有指定,OpenTSDB会从以下路径寻找配置文件:

  • ./opentsdb.conf
  • /etc/opentsdb.conf
  • /etc/opentsdb/opentsdb.conf
  • /opt/opentsdb/opentsdb.conf

如果一个合法的配置文件没有找到并且一些必须参数没有设置,TSD进程将不会启动。

配置文件中可配置的属性请参考:Properties

3.2 基本概念

在深入理解OpenTSDB之前,需要了解一些基本概念。

  • Cardinality。基数,在数学中定义为一个集合中的一些元素,在数据库中定义为一个索引的一些唯一元素,在OpenTSDB定义为:
  • 一个给定指标的一些唯一时间序列
  • 和一个标签名称相关联的一些唯一标签值

在OpenTSDB中拥有高基数的指标在查询过程中返回的值要多于低基数的指标,这样花费的时间也就越多。

Compaction。在OpenTSDB中,会将多列合并到一列之中以减少磁盘占用空间,这和hbase中的Compaction不一样。这个过程会在TSD写数据或者查询过程中不定期的发生。

Data Point。每一个指标可以被记录为某一个时间点的一个数值。Data Point包括以下部分:

  • 一个指标:metric
  • 一个数值
  • 这个数值被记录的时间戳
  • 多个标签

Metric。一个可测量的单位的标称。metric不包括一个数值或一个时间,其仅仅是一个标签,包含数值和时间的叫datapoints,metric是用逗号连接的不允许有空格,例如:

  • hours.worked
  • webserver.downloads
  • accumulation.snow

Tags。一个metric应该描述什么东西被测量,在OpenTSDB中,其不应该定义的太简单。通常,更好的做法是用Tags来描述具有相同维度的metric。Tags由tagk和tagv组成,前者表示一个分组,后者表示一个特定的项。

Time Series。一个metric的带有多个tag的data point集合。

Timestamp。一个绝对时间,用来描述一个数值或者一个给定的metric是在什么时候定义的。

Value。一个Value表示一个metric的实际数值。

UID。在OpenTSDB中,每一个metric、tagk或者tagv在创建的时候被分配一个唯一标识叫做UID,他们组合在一起可以创建一个序列的UID或者TSUID。在OpenTSDB的存储中,对于每一个metric、tagk或者tagv都存在从0开始的计数器,每来一个新的metric、tagk或者tagv,对应的计数器就会加1。当data point写到TSD时,UID是自动分配的。你也可以手动分配UID,前提是auto metric被设置为true。默认地,UID被编码为3Bytes,每一种UID类型最多可以有16,777,215个UID。你也可以修改源代码改为4Bytes。UID的展示有几种方式,最常见的方式是通过http api访问时,3 bytes的UID被编码为16进制的字符串。例如,UID为1的写为二进制的形式为000000000000000000000001,最为一个无符号的byte数组,其可以表示为[0,0,1],编码为16进制字符串为000001,其中每一位左边都被补上0,如果其不足两位。故,UID为255的会显示为[0,0,255]0000FF

关于为什么使用UID而不使用hashes,可以参考:why-uids

TSUID。当一个data point被写到OpenTSDB时,其row key格式为:<metric_UID><timestamp><tagk1_UID><tagv1_UID>[...<tagkN_UID><tagvN_UID>],不考虑时间戳的话,将其余部分都转换为UID,然后拼在一起,就可以组成为TSUID。

Metadata。主要用于记录data point的一些附加的信息,方便搜索和跟踪,分为UIDMeta和TSMeta。

每一个UID都有一个metadata记录保存在tsdb-uid表中,每一个UID包括一些不可变的字段,如uidtypenamecreated字段表示什么时候被创建,还可以有一些额外字段,如descriptionnotesdisplayName和一些custom key/value对,详细信息,可以查看 /api/uid/uidmeta

同样,每一个TSUID可以对应一个TSMeta,记录在tsdb-uid中,其包括的字段有tsuidmetrictagslastReceivedcreated,可选的字段有descriptionnotes,详细信息,可以查看/api/uid/tsmeta

开启Metadata有以下几个参数:

  • tsd.core.meta.enable_realtime_uid
  • tsd.core.meta.enable_tsuid_tracking
  • tsd.core.meta.enable_tsuid_incrementing
  • tsd.core.meta.enable_realtime_ts

metadata的另外一个形式是Annotations,详细说明,请参考annotations

Tree

3.3 数据存储方式

OpenTSDB使用HBase作为后端存储,在安装OpenTSDB之前,需要先启动一个hbase节点或者集群,然后再执行建表语句src/create_table.sh创建hbase表。建表语句如下:

从上面可以看出一共创建了4张表,并且可以设置是否压缩、是否启用布隆过滤、保存版本号等等,如果追求hbase读写性能,还可以预建分区。

3.3.1 Data Table Schema

在OpenTSDB中,所有数据存储在一张叫做tsdb的表中,这是为了充分利用hbase有序和region分布式的特点。所有的值都保存在列族t中。

rowkey为<metric_uid><timestamp><tagk1><tagv1>[...<tagkN><tagvN>],UID默认编码为3 Bytes,而时间戳会编码为4 Bytes

OpenTSDB的tsdb启动之后,会监控指定的socket端口(默认为4242),接收到监控数据,包括指标、时间戳、数据、tag标签,tag标签包括tag名称ID和tag值ID。例如:

对于指标myservice.latency.avg的ID为:[0, 0, -69],reqtype标签名称的ID为:[0, 0, 1], foo标签值的ID为:[0, 1, 11], 标签名称的ID为:[0, 0, 2] web42标签值的ID为:[0, -7, 42],他们组成rowkey:

row表示格式为: 每个数字对应1 byte

  • [0, 0, -69] metric ID
  • [77, 4, -99, 32] base timestamp = 1292148000. timestamps in the row key are rounded down to a 60 minute boundary。也就是说对于同一个小时的metric + tags相同的数据都会存放在一个row下面
  • [0, 0, 1] "reqtype" index
  • [0, 1, 11] "foo" index
  • [0, 0, 2] "host" index
  • [0, -7, 42] "web42" index

NOTE:可以看到,对于metric + tags相同的数据都会连续存放,且metic相同的数据也会连续存放,这样对于scan以及做aggregation都非常有帮助

column qualifier 占用2 bytes或者4 bytes,占用2 bytes时表示以秒为单位的偏移,格式为:

  • 12 bits:相对row表示的小时的delta, 最多2^ 12 = 4096 > 3600因此没有问题
  • 4 bits:format flags
    • 1 bit: an integer or floating point
    • 3 bits: 标明数据的长度,其长度必须是1、2、4、8。000表示1个byte,010表示2byte,011表示4byte,100表示8byte

占用4 bytes时表示以毫秒为单位的偏移,格式为:

  • 4 bits:十六进制的1或者F
  • 22 bits:毫秒偏移
  • 2 bit:保留
  • 4 bits: format flags
    • 1 bit: an integer or floating point,0表示整数,1表示浮点数
    • 3 bits: 标明数据的长度,其长度必须是1、2、4、8。000表示1个byte,010表示2byte,011表示4byte,100表示8byte

举例:

对于时间戳为1292148123的数据点来说,其转换为以小时为单位的基准时间(去掉小时后的秒)为129214800,偏移为123,转换为二进制为1111011,因为该值为整数且长度为8位(对应为2byte,故最后3bit为100),故其对应的列族名为:0000011110110100,将其转换为十六进制为07B4

value 使用8bytes存储,既可以存储long,也可以存储double。

总结一下,tsdb表结构如下:

cassandra

3.3.2 UID Table Schema

一个单独的较小的表叫做tsdb-uid用来存储UID映射,包括正向的和反向的。存在两列族,一列族叫做name用来将一个UID映射到一个字符串,另一个列族叫做id,用来将字符串映射到UID。列族的每一行都至少有以下三列中的一个:

  • metrics 将metric的名称映射到UID
  • tagk 将tag名称映射到UID
  • tagv 将tag的值映射到UID

如果配置了metadata,则name列族还可以包括额外的metatata列。

  • id 列族

Row Key - 将会是一个分配到UID的字符串,例如,对于一个指标可能有一个值为sys.cpu.user或者对于一个标签其值可能为42

Column Qualifiers - 上面三种列类型中一种。

Column Value - 一个无符号的整数,默认被编码为3个byte,其值为UID。

例如以下几行数据是从tsdb-uid表中查询出来的数据,第一个列为row key,第二列为"列族:列名",第三列为值,对应为UID

  • name 列族

Row Key - 为UID

Column Qualifiers - 上面三种列类型中一种或者为metrics_metatagk_metatagv_meta

Column Value - 与UID对应的字符串,对于一个*_meta列,其值将会是一个UTF-8编码的JSON格式字符串。不要在OpenTSDB外部去修改该值,其中的字段顺序会影响CAS调用。

例如,以下几行数据是从tsdb-uid表中查询出来的数据,第一个列为row key,第二列为"列族:列名",第三列为值,对应为UID

总结一下,tsdb-uid表结构如下:

cassandra

上图对应的一个datapoint如下:

从上图可以看出tsdb-uid的表结构以及数据存储方式,对于一个data point来说,其被保存到opentsdb之前,会对metricstagktagvmetric_metatagk_metatagv_meta生成一个UID(如上图中的000001),然后将其插入hbase表中,rowkey为UID,同时会存储多行记录,分别保存metricstagktagvmetric_metatagk_metatagv_meta到UID的映射。

3.3.3 Meta Table Schema

这个表是OpenTSDB中不同时间序列的一个索引,可以用来存储一些额外的信息。这个表名称叫做tsdb-meta,该表只有一个列族name,两个列,分别为ts_metats_ctr,该表中数据如下:

Row Key 和tsdb表一样,其中不包含时间戳,<metric_uid><tagk1><tagv1>[...<tagkN><tagvN>]

TSMeta Column 和UIDMeta相似,其为UTF-8编码的JSON格式字符串

ts_ctr Column 计数器,用来记录一个时间序列中存储的数据个数,其列名为ts_ctr,为8位有符号的整数。

3.3.4 Tree Table Schema

索引表,用于展示树状结构的,类似于文件系统,以方便其他系统使用,例如:Graphite

3.4 如何写数据

3.5 如何查询数据

3.6 CLI Tools

tsdb支持以下参数:

通过以下命令创建指标:

执行上述命令的结果如下:

3.11 Utilities

3.12 Logging

4. HTTP API

5. 谁在用OpenTSDB

  • StumbleUpon StumbleUpon is the easiest way to find cool new websites, videos, photos and images from across the Web
  • box Box simplifies online file storage, replaces FTP and connects teams in online workspaces.
  • tumblr 一个轻量级博客,用户可以跟进其他的会员并在自己的页面上看到跟进会员发表的文章,还可以转发他人在Tumblr上的文章

6. KairosDB

KairosDB是一个快速可靠的分布式时间序列数据库,主要用于Cassandra当然也可以适用与HBase。KairosDB是在OpenTSDB基础上重写的,他不仅可以在HBase上存储数据还支持Cassandra。

KairosDB主页:https://code.google.com/p/kairosdb/

7. 参考资料

转自:http://blog.javachen.com/2014/01/22/all-things-opentsdb/#

MAC查看端口占用情况

 

命令 lsof -i tcp:port  (port替换成端口号,比如6379)可以查看该端口被什么程序占用,并显示PID,方便KILL

vim中复制,剪切一行,快速查找某一单词的命令

  1. 使用yy复制一行

    使用 行数n+yy 复制n行

    使用p对复制的行进行粘贴

  2.  

    使用dd剪切一行

    使用 行数n+dd 剪切n行

    使用p对剪切的行进行粘贴

  3.  

    在vi中查找某一个单词,先按Esc,再按 冒号 进入末行模式,输入/word或者?word查找单词word,如果想接着查找该单词,按n或N。

    vim中复制,剪切一行,快速查找某一单词的命令
    vim中复制,剪切一行,快速查找某一单词的命令
  4.  
    在vi中快速定位到某一行,进入末行模式,输入行号,按回车即可。快速到达第一行和最后一行可以用快捷键,gg定位到第一行,G定位到最后一行
    vim中复制,剪切一行,快速查找某一单词的命令

vim如何删除文件中所有东西

方法1:    按ggdG

方法2:       :%d

Docker exec与Docker attach

不论是开发者是运维人员,都经常有需要进入容器的诉求。 
目前看,主要的方法不外乎以下几种: 
1. 使用ssh登陆进容器 
2. 使用nsenter、nsinit等第三方工具 
3. 使用docker本身提供的工具

方法1需要在容器中启动sshd,存在开销和攻击面增大的问题。同时也违反了Docker所倡导 
的一个容器一个进程的原则。 
方法2需要额外学习使用第三方工具。 
所以大多数情况最好还是使用Docker原生方法,Docker目前主要提供了Docker exec和 
Docker attach两个命令。

以下在fedora21,docker1.7上验证。

Docker attach

Docker attach可以attach到一个已经运行的容器的stdin,然后进行命令执行的动作。 
但是需要注意的是,如果从这个stdin中exit,会导致容器的停止。


[root@localhost temp]# docker ps
CONTAINER ID        IMAGE                       COMMAND             CREATED              STATUS              PORTS               NAMES
2327e7eab0ed        busybox:buildroot-2014.02   "/bin/sh"           About a minute ago   Up About a minute                       bb2
[root@localhost temp]# docker attach bb2
/ # ls
bin      dev      etc      home     lib      lib64    linuxrc  media    mnt      opt      proc     root     run      sbin     sys      tmp      usr      var
/ # pwd
/
/ #

Docker exec

关于-i、-t参数

可以看出只用-i时,由于没有分配伪终端,看起来像pipe执行一样。但是执行结果、命令 
返回值都可以正确获取。


[root@localhost temp]# docker exec -i bb2 /bin/sh
date
Tue Jul 14 04:01:11 UTC 2015
echo $?
0
dir
/bin/sh: dir: not found
echo $?
127

使用-it时,则和我们平常操作console界面类似。而且也不会像attach方式因为退出,导致 
整个容器退出。 
这种方式可以替代ssh或者nsenter、nsinit方式,在容器内进行操作。


[root@localhost temp]# docker exec -it bb2 /bin/sh
/ # pwd
/
/ # echo $?
0
/ # dir
/bin/sh: dir: not found
/ # echo $?
127

如果只使用-t参数,则可以看到一个console窗口,但是执行命令会发现由于没有获得stdin 
的输出,无法看到命令执行情况。


[root@localhost temp]# docker exec -t bb2 /bin/sh
/ # pwd

hanging....
[root@localhost temp]# docker exec -t bb2 pwd
/
[root@localhost temp]# echo $?
0
[root@localhost temp]# docker exec -t bb2 dir
2015/07/14 04:03:57 docker-exec: failed to exec: exec: "dir": executable file not found in $PATH
[root@localhost temp]# echo $?
0

docker exec执行后,会命令执行返回值。(备注Docker1.3似乎有Bug,不能正确返回命令执行结果)


[root@localhost temp]# docker exec -it bb cat /a.sh
echo "running a.sh"
exit 10
[root@localhost temp]# docker exec -t bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10
[root@localhost temp]# docker exec -it bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10
[root@localhost temp]# docker exec -i bb /a.sh
running a.sh
[root@localhost temp]# echo $?
10
关于-d参数

在后台执行一个进程。可以看出,如果一个命令需要长时间进程,使用-d参数会很快返回。 
程序在后台运行。


[root@localhost temp]# docker exec -d bb2 /a.sh
[root@localhost temp]# echo $?
0

如果不使用-d参数,由于命令需要长时间执行,docker exec会卡住,一直等命令执行完成 
才返回。


[root@localhost temp]# docker exec  bb2 /a.sh
^C[root@localhost temp]#
[root@localhost temp]#
[root@localhost temp]# docker exec -it  bb2 /a.sh
^C[root@localhost temp]#
[root@localhost temp]# docker exec -i  bb2 /a.sh
^C[root@localhost temp]# docker exec -t  bb2 /a.sh
^C[root@localhost temp]#



使用 Git 管理项目 - reset 与 rebase

144 
作者 Jovey 
2015.11.04 17:43 字数 1313 阅读 3749评论 2

在日常管理项目的过程中,可能会遇到提交的 commit/merge 并不是想要的,或是操作失误提交了,那么此时我们需要把不想要的 commit/merge 取消掉,如果做到呢?Git 为我们提供了一个 reset command,很好地解决了这个问题。

reset

1. 命令说明

$ git reset [--hard|soft|mixed|merge|keep] [<commit>|<HEAD>]

常用的是[--hard|soft|mixed],本文主要使用--hard作为例子进行说明。

2. 本地仓库

在本地仓库执行 $ git reset --hard HEAD^ 可以将本地的仓库回滚到上一次提交时的状态,HEAD^指的是上一次提交。

同时你也可以执行 $ git reset --hard fc232ae 将其回滚到 fc232ae commit 时的状态。

3. 远程仓库

以上操作只会对本地仓库造成影响,而远程仓库的源码和 commit 信息并不会因此改变。那么此时我们需要另外一个 command 来改变远程仓库的状态。

注意,此时不要在上一步的操作之后执行$ git pull ,因为这个操作会使本地仓库的状态与远程同步。

$ git push origin [branch] -f

执行此命令后,Git 会将远程仓库的状态与本地仓库的保持一致,即回滚状态。

在更新代码时,难免一次到位,此时就会生成许许多多的 commit 。比如同一个文件,反复地修改代码,反复地提交,此时会有5,6个 commit 甚至更多,那么你会在提交 list 中看到一大串的 commit 记录,会觉得很是头疼,杂乱。此时我们需要把这些 commit 整合以下,合并到一个 commit 中,其他的 commit 都 squash 到第一 commit 中,那么就需要用到 rebase

rebase

1. 说明

$ git rebase -i [branch|<commit>]

你可以直接进入某个分支的 rebase 也可以进入某次 commit 的 rebase,如果你是项将某些 commit 合并,那么建议使用 $ git rebase -i <commit>

此外 rebase 还提供三个操作命令,分别是 --continue--absort 和 --skip,这三个命令的意思分别是“继续”、“退出”和“跳过”。

2. 查看记录

$ git log

执行此命令即可看到当前分支下所有的提交记录,然后根据个人需要复制其中的 commit 的 SHA 进行 rebase 操作。

3. rebase

执行:

$ git rebase -i 9cbc329

然后就会看到:

pick fb554f5 This is commit 1
pick 2bd1903 This is commit 2
pick d987ebf This is commit 3
# Rebase 9cbc329..d987ebf onto 9cbc329
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

那么其中 pick fb554f5 This is commit 1我们可以把它分成三部分去解释:

  • pick::操作,即 rebase command
  • fb554f5:commit shortID,提交的简写ID
  • This is commit 1: commit message,提交时填写的提交信息

此时我们可以看到输出结果中所提供的一些操作方法,比如 picksquashedit 等。那么重要的是 pick 和 squash

接着我们需要把 2bd1903 和 d987ebf 合并到 fb554f5 中,做如下操作(注意:此时是 VIM 的操作界面,熟悉 Linux 的同学可以无视,不熟悉的可以简略的指导):

pick fb554f5 This is commit 1
squash 2bd1903 This is commit 2
squash d987ebf This is commit 3
# Rebase 9cbc329..d987ebf onto 9cbc329
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

在做完以上修改操作后输入 :x 保存文件并退出界面,然后就会看到:

$ git rebase -i 9cbc329
rebase in progress; onto 9cbc329
You are currently rebasing branch 'master' on '9cbc329'.

nothing to commit, working directory clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

    git commit --allow-empty

Otherwise, please use 'git reset'
Could not apply 9cbc329f722f8e531496da70ee3857b031574b6d... squash commit on rebase

此时用 $ git status 查看会看到:

$ git status
rebase in progress; onto 9cbc329
You are currently rebasing branch 'master' on '9cbc329'.
  (all conflicts fixed: run "git rebase --continue")

nothing to commit, working directory clean

紧接着我们需要执行 $ git rebase --continue 操作:

$ git rebase --continue
[detached HEAD 2bd1903...d987ebf] squash commit on rebase
 Date: Tue Nov 3 10:09:43 2015 +0800
 1 file changed, 149 insertions(+), 154 deletions(-)
 rewrite test.js (72%)
Successfully rebased and updated refs/heads/master.

最后我们需要把修改合并好的 commit push 到远程仓库上:

$ git push origin [branch] -f

到此为止,整个 rebase 操作都已完成。
你会看到类似:


before


变成类似:


after

简略的指导

在 VIM 的操作界面下,需要按 I/Insert 键进行插入修改文本操作,修改完文本之后需要按 Esc 键退出编辑状态,然后输入 :q 是离开,输入 :!q 是强制离开,输入 :x 是保存修改并离开。
在 rebase 修改文本结束后需要输入 :x 进行保存。




nc -z 192.168.1.103 22; echo $?
 
原文地址:https://www.cnblogs.com/alexyuyu/p/6426860.html