Info

Jaxb是JavaEE的规范.全称Java Architecture for XML Binding. 可以根据XML Schema产生Java类的技术.JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档. JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。在实际使用不需要引入新的jar.

项目主页

Class & Interface

  • AXBContext类,是应用的入口,用于管理XML/Java绑定信息。

  • Marshaller接口,将Java对象序列化为XML数据。

  • Unmarshaller接口,将XML数据反序列化为Java对象。

    JAXBContext jc = JAXBContext.newInstance(“com.acme.foo”); Unmarshaller u = jc.createUnmarshaller(); Object element = u.unmarshal( new File(“foo.xml”)); Marshaller m = jc.createMarshaller(); m.marshal(element, …);

常用注解

  • @XmlType

@XmlType用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。它有三个属性:name、propOrder、namespace,经常使用的只有前两个属性。

@XmlType(name = "basicStruct", propOrder = {
	"intValue",
	"stringArray",
	"stringValue"
)
  • @XmlElement

@XmlElement将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。

  • @XmlRootElement

@XmlRootElement用于类级别的注解,对应xml的跟元素,常与 @XmlType 和 @XmlAccessorType一起使用。

@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Address {}
  • @XmlAttribute

@XmlAttribute用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。

  • @XmlAccessorType

@XmlAccessorType用于指定由java对象生成xml文件时对java对象属性的访问方式。常与@XmlRootElement、@XmlType一起使用。它的属性值是XmlAccessType的4个枚举值

  • @XmlAccessorOrder

@XmlAccessorOrder用于对java对象生成的xml元素进行排序。

  • @XmlTransient

@XmlTransient用于标示在由java对象映射xml时,忽略此属性。

  • @XmlJavaTypeAdapter

@XmlJavaTypeAdapter常用在转换比较复杂的对象时,如map类型或者格式化日期等。使用此注解时,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。

//xxx为自己定义的adapter类
@XmlJavaTypeAdapter(value=xxx.class)
  • @Temporal(TemporalType.XXXX)

JPA中的时间处理注解,非JAXB

  • @XmlElementWrapper

@XmlElementWrapper注解表示生成一个包装 XML 表示形式的包装器元素。 此元素主要用于生成一个包装集合的包装器 XML 元素。

	int[] names;

	// XML Serialization Form 1 (Unwrapped collection)
	<names> ...</names>
	<names> ...</names>

	// XML Serialization Form 2 ( Wrapped collection )
	<wrapperElement>
	<names> value-of-item </names>
	<names> value-of-item </names>
		   ....
	</wrapperElement>

Read More

1. Info

Jersey是JAX-RS(JSR311)开源参考实现用于构建RESTful Web service。 此外Jersey还提供一些额外的API和扩展机制,所以开发人员能够按照自己的需要对Jersey进行扩展。

软件首页

软件文档

2. 依赖

2.1. 兼容性

Jersey 2.6 => java se 1.6+

Jersey 2.7 => java se 1.7+

2.2. 使用

  • 在应用服务器(Servlet 容器)中使用

	<dependency>
		<groupId>org.glassfish.jersey.containers</groupId>
		<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core"  -->
		<artifactId>jersey-container-servlet</artifactId>
		<version>2.11</version>
	</dependency>
	<!-- Required only when you are using JAX-RS Client -->
	<dependency>
		<groupId>org.glassfish.jersey.core</groupId>
		<artifactId>jersey-client</artifactId>
		<version>2.11</version>
	</dependency>

  • Other

    // TODO 待整理

3. JAX-RS 应用

JAX-RS解析

3.1. Root Resource Classes

Root Resource Classes 是使用 @Path 标注并且有一个方法被 @Path 或 HTTP 方法(@Get,@Put,@Post,@Delete等)标注.

3.1.1. @Path

@Path 注解是一个相对的 URI 路径.如:

@Path("/users/{username}")

将响应这个 URL: http://example.com/users/Galileo

为了获取 username 的值,可以在请求方法的参数中使用 @PathParam 注解.

@Path("/users/{username}")
public class UserResource {

	@GET
	@Produces("text/xml")
	public String getUser(@PathParam("username") String userName) {
		...
	}
}

可以使用正则表到时来限定(username)参数.

@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")

若 username 不匹配,将响应404页面.

3.1.2. @Get,@Put,@Post,@Delete…(Http 方法)

@GET, @PUT, @POST, @DELETE 和 @HEAD 是 JAX-RS 中定义的资源方法注解,它们与 HTTP 里的方法是一一对应的.

即使没有明确标注,JAX-RS 运行时也会默认自动支持 HEAD 和 OPTIONS 方法.

3.1.3. @Produces

@Produces 可以应用与类和方法上.其用于指明将要返回给客户端的资源表述的 MIME 媒体类型.

@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
	@GET
	public String doGetAsPlainText() {
		...
	}

	@GET
	@Produces("text/html")
	public String doGetAsHtml() {
		...
	}
}

上例中,方法中的媒体类型将覆盖类中定义的.

可以对方法指定多个媒体类型.

@GET
@Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
	...
}

可以指定媒体类型的 quality 因子.

@GET
@Produces({"application/xml; qs=0.9", "application/json"})
public String doGetAsXmlOrJson() {
	...
}

如果客户端同时接受”application/xml”和”application/json”,在此例,服务器会返回”application/json”,因为”application/xml”的 quality 因子比较低.

3.1.4. @Consumes

@Consumes 用来指定可以接受客户端发送过来的 MIME 媒体类型,同样可以用于类或者方法,也可以指定多个 MIME 媒体类型.

@POST
@Consumes("text/plain")
public void postClichedMessage(String message) {
	// Store the message
}

注意:资源方法的返回值为 void,这表示客户端接受到的响应状态码将为204.

3.2. 参数注解(@*Param)

  • @PathParam

可以获取URI中指定规则的参数.

  • @QueryParam

用于获取GET请求中的查询参数.

  • @DefaultValue

可以为参数设置默认值.

  • @MatrixParam

  • @HeaderParam

  • @cookieParam

  • @FormParam

从POST请求的表单参数中获取数据.

  • @BeanParam

当请求参数很多时,比如客户端提交一个修改用户的PUT请求,请求中包含很多项用户信息。这时可以用@BeanParam

public class MyBeanParam {
	@PathParam("p")
	private String pathParam;

	@MatrixParam("m")
	@Encoded
	@DefaultValue("default")
	private String matrixParam;

	@HeaderParam("header")
	private String headerParam;

	private String queryParam;

	public MyBeanParam(@QueryParam("q") String queryParam) {
		this.queryParam = queryParam;
	}

	public String getPathParam() {
		return pathParam;
	}
	...
}

//Injection of MyBeanParam as a method parameter:
@POST
public void post(@BeanParam MyBeanParam beanParam, String entity) {
	final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p"
	...
}

3.3. 子资源

@Singleton
@Path("/printers")
public class PrintersResource {

	@GET
	@Produces({"application/json", "application/xml"})
	public WebResourceList getMyResources() { ... }

	@GET @Path("/list")
	@Produces({"application/json", "application/xml"})
	public WebResourceList getListOfPrinters() { ... }

	@GET @Path("/jMakiTable")
	@Produces("application/json")
	public PrinterTableModel getTable() { ... }

	@GET @Path("/jMakiTree")
	@Produces("application/json")
	public TreeModel getTree() { ... }

	@GET @Path("/ids/{printerid}")
	@Produces({"application/json", "application/xml"})
	public Printer getPrinter(@PathParam("printerid") String printerId) { ... }

	@PUT @Path("/ids/{printerid}")
	@Consumes({"application/json", "application/xml"})
	public void putPrinter(@PathParam("printerid") String printerId, Printer printer) { ... }

	@DELETE @Path("/ids/{printerid}")
	public void deletePrinter(@PathParam("printerid") String printerId) { ... }
}

如果请求的 URL 为”printers”,则上面没有使用 @Path 注解的方法将被调用.如果请求的 URL 为”printers/list”,则自资源方法 getListOfPrinters 将被调用.

@Path("/item")
public class ItemResource {
	@Context UriInfo uriInfo;

	@Path("content")
	public ItemContentResource getItemContentResource() {
		return new ItemContentResource();
	}

	@GET
	@Produces("application/xml")
		public Item get() { ... }
	}
}

public class ItemContentResource {

	@GET
	public Response get() { ... }

	@PUT
	@Path("{version}")
	public void put(@PathParam("version") int version,
					@Context HttpHeaders headers,
					byte[] in) {
		...
	}
}

如果请求的 URL 为”item/content”,则 getItemContentResource 将被调用.

@Path("/item")
public class ItemResource {

	@Path("/")
	public ItemContentResource getItemContentResource() {
		return new ItemContentResource();
	}
}

请求为”/item/locator”或为”/item”,getItemContentResource 都会被调用.

@Singletion

import javax.inject.Singleton;

@Path("/item")
public class ItemResource {
	@Path("content")
	public Class<ItemContentSingletonResource> getItemContentResource() {
		return ItemContentSingletonResource.class;
	}
}

@Singleton
public class ItemContentSingletonResource {
	// this class is managed in the singleton life cycle
}

programmatic resource model

import org.glassfish.jersey.server.model.Resource;

@Path("/item")
public class ItemResource {

	@Path("content")
	public Resource getItemContentResource() {
		return Resource.from(ItemContentSingletonResource.class);
	}
}

3.4. Root Resource classes 的生命周期

默认的生命周期是每个请求的,即对应每个请求都会有一个实例被创建.

生命周期

  • 默认生命周期 @RequestScoped(or none)

  • Per-lookup @PerLookup

  • Singleton @Singleton

3.5. 注入规则

3.6. @Context 的使用

可以通过@Context 注释获取ServletConfig、ServletContext、HttpServletRequest、HttpServletResponse和HttpHeaders等对象.

4. 应用部署与运行时

4.1. JAX-RS Application 模型

JAX-RS 提供了一个部署无关的虚类 Application 用以发布 root 资源和 provider classes. Web Service 可以继承这个类来发布自己的 root 资源和 provider classes.

public class MyApplication extends Application {
	@Override
	public Set<Class<?>> getClasses() {
		Set<Class<?>> s = new HashSet<Class<?>>();
		s.add(HelloWorldResource.class);
		return s;
	}
}

Jersey 也实现了自己的 Application 类 ResourceConfig.该类可以直接实例化或继承并在构造函数中进行配置来发布资源.

// 下面的 Application 会在部署时扫描"org.foo.rest"和"org.bar.rest"包中的 JAX-RS 组件
public class MyApplication extends ResourceConfig {
	public MyApplication() {
		packages("org.foo.rest;org.bar.rest");
	}
}

4.2. Classpath Scanning 配置

// TODO 待整理

4.3. HTTP Server 部署

Java base HTTP servers 展示了一种简单灵活的方式来部署 Jersey 应用.Jersey 自定义的工厂方法可以返回正确的 HTTP server 实例.

4.3.1. JDK HTTP Server

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);

需要的依赖

<dependency>
	<groupId>org.glassfish.jersey.containers</groupId>
	<artifactId>jersey-container-jdk-http</artifactId>
	<version>2.11</version>
</dependency>

4.3.2. Simple server

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
	ResourceConfig config = new ResourceConfig(MyResource.class);
	SimpleContainer server = SimpleContainerFactory.create(baseUri, config);

需要的依赖

<dependency>
	<groupId>org.glassfish.jersey.containers</groupId>
	<artifactId>jersey-container-simple-http</artifactId>
	<version>2.11</version>
</dependency>

4.3.3. Jetty HTTP Server

URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
Server server = JettyHttpContainerFactory.createServer(baseUri, config);

需要的依赖

<dependency>
	<groupId>org.eclipse.jetty</groupId>
	<artifactId>jetty-server</artifactId>
	<version>2.11</version>
</dependency>

4.4. 基于 Servlet 的部署

4.4.1. Servlet 2.x Container

  • 作为 Servlet

	<web-app>
		<servlet>
			<servlet-name>MyApplication</servlet-name>
			<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
			<init-param>
				...
			</init-param>
		</servlet>
		...
		<servlet-mapping>
			<servlet-name>MyApplication</servlet-name>
			<url-pattern>/myApp/*</url-pattern>
		</servlet-mapping>
		...
	</web-app>

  • 作为 Servlet Filter

	<web-app>
		<filter>
			<filter-name>MyApplication</filter-name>
			<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
			<init-param>
				...
			</init-param>
		</filter>
		...
		<filter-mapping>
			<filter-name>MyApplication</filter-name>
			<url-pattern>/myApp/*</url-pattern>
		</filter-mapping>
		...
	</web-app>

<init-param> 的内容可以如下定义.

  1. 自定义 Application 子类

	<init-param>
		<param-name>javax.ws.rs.Application</param-name>
		<param-value>org.foo.MyApplication</param-value>
	</init-param>

  1. 扫描Jersey包

	<init-param>
		<param-name>jersey.config.server.provider.packages</param-name>
		<param-value>
			org.foo.myresources,org.bar.otherresources
		</param-value>
	</init-param>
	<init-param>
		<param-name>jersey.config.server.provider.scanning.recursive</param-name>
		<param-value>false</param-value>
	</init-param>

  1. 指定具体的 resource 和 provider 类

	<init-param>
		<param-name>jersey.config.server.provider.classnames</param-name>
		<param-value>
			org.foo.myresources.MyDogResource,
			org.bar.otherresources.MyCatResource
		</param-value>
	</init-param>

4.4.2. Servlet 3.x Container

// TODO 待整理

5. 表述与响应

5.1. 表述与 Java 类型

  1. All media types (*/*)

    • byte[]

    • java.lang.String

    • java.io.Reader (inbound only)

    • java.io.File

    • javax.activation.DataSource

    • javax.ws.rs.core.StreamingOutput (outbound only)

  2. XML media types (text/xml, application/xml and application/…+xml)

    • javax.xml.transform.Source

    • javax.xml.bind.JAXBElement

    • Application supplied JAXB classes (types annotated with @XmlRootElement or@XmlType)

  3. Form content (application/x-www-form-urlencoded)

    • MultivaluedMap<String,String>
  4. Plain text (text/plain)

    • java.lang.Boolean

    • java.lang.Character

    • java.lang.Number

5.2. 构造响应

可以通过 ResponseResponse.ResponseBuilder 来构造并返回响应的附加信息.

  1. 返回 201 状态码

    @POST @Consumes(“application/xml”) public Response post(String content) { URI createdUri = … create(content); return Response.created(createdUri).build(); }

  2. 自定义天添加 Entity body 响应

    @POST @Consumes(“application/xml”) public Response post(String content) { URI createdUri = … String createdContent = create(content); return Response.created(createdUri).entity(Entity.text(createdContent)).build(); }

5.3. WebApplicationException 和 响应的异常映射

JAX-RS 允许定义 Java 异常与 HTTP 错误响应的直接映射.

通过抛出 CustomNotFoundException 来向客户端返回一个错误的 HTTP 响应.

@Path("items/{itemid}/")
public Item getItem(@PathParam("itemid") String itemid) {
  Item i = getItems().get(itemid);
  if (i == null) {
	throw new CustomNotFoundException("Item, " + itemid + ", is not found");
  }

  return i;
}

具体应用程序异常的实现

public class CustomNotFoundException extends WebApplicationException {

  /**
  * Create a HTTP 404 (Not Found) exception.
  */
  public CustomNotFoundException() {
	super(Responses.notFound().build());
  }

  /**
  * Create a HTTP 404 (Not Found) exception.
  * @param message the String that is the entity of the 404 response.
  */
  public CustomNotFoundException(String message) {
	super(Response.status(Responses.NOT_FOUND).
	entity(message).type("text/plain").build());
  }
}

另一情况,最好通过自定义异常映射 provider 来映射一个已存在的异常.这个 provider 必须继承 ExceptionMapper 接口.

@Provider
public class EntityNotFoundMapper implements ExceptionMapper<javax.persistence.EntityNotFoundException> {
  public Response toResponse(javax.persistence.EntityNotFoundException ex) {
	return Response.status(404).
	  entity(ex.getMessage()).
	  type("text/plain").
	  build();
  }
}

若 Throwable 类是 WebApplicationException 的实例,并且 Response.hasEntity() 为真,将不执行 ExceptionMapper.toResponse 函数.

5.4. Conditional GETs 和 304 响应

public SparklinesResource(
  @QueryParam("d") IntegerList data,
  @DefaultValue("0,100") @QueryParam("limits") Interval limits,
  @Context Request request,
  @Context UriInfo ui) {
  if (data == null) {
	throw new WebApplicationException(400);
  }

  this.data = data;
  this.limits = limits;

  if (!limits.contains(data)) {
	throw new WebApplicationException(400);
  }

  this.tag = computeEntityTag(ui.getRequestUri());

  if (request.getMethod().equals("GET")) {
	Response.ResponseBuilder rb = request.evaluatePreconditions(tag);
	if (rb != null) {
	  throw new WebApplicationException(rb.build());
	}
  }
}

15. 安全

15.1. SecurityContext

16. 对 WADL 的支持

默认情况下 jersey 是自动开启 WADL 的支持的.默认 Path("application.wadl")

要禁用 WADL ,请在应用中(web.xml 或 Application.getProperties())进行如下配置:

jersey.config.server.wadl.disableWadl=true

. MVC Templates

// TODO 待整理

参考

JAX-RS解析

使用 Jersey 和 Apache Tomcat 构建 RESTful Web 服务


Read More

简介

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。

主要的特性有:

  1. 快速.
  2. 简单.
  3. 多种缓存策略
  4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
  5. 缓存数据会在虚拟机重启的过程中写入磁盘
  6. 可以通过RMI、可插入API等方式进行分布式缓存
  7. 具有缓存和缓存管理器的侦听接口
  8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
  9. 提供Hibernate的缓存实现
  10. 等等

配置

基本配置文件

Ehcache默认的配置文件是ehcache.xml(没有该文件,Ehcache会到类路径下找ehcache-failsafe.xml文件。而ehcache-failsafe.xml被包含在jar包中)。 内容如下:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<!-- <diskStore path="c:\\mdcp_temp" />-->
 <cacheManagerEventListenerFactory class="" properties="" />

 <defaultCache>
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="600"
        overflowToDisk="false"
 </defaultCache>

<cache>
        name="configCache"
        maxElementsInMemory="1000"
        maxElementsOnDisk="1000"
        eternal="true"
        timeToIdleSeconds="300"
        timeToLiveSeconds="1000"
        overflowToDisk="false"
< /cache>

</ehcache>

这里配置了一个名为configCache的缓存实例。参数说明如下:

  • name : 元素名称即缓存实例的名称。
  • maxElementsInMemory : 设定内存中保存对象的最大值。
  • overflowToDisk : 设置当内存中缓存到达maxElementsInMemory指定值时是否可以写到硬盘上。
  • eternal : 设置内存中的对象是否为永久驻留对象。如果是则无视timeToIdleSeconds和timeToLiveSeconds两个属性。
  • timeToIdleSeconds : 设置某个元素消亡前的停顿时间。指元素创建以后,最后一次访问缓存的日期至失效之时的时间间隔。
  • timeToLiveSeconds : 设置某个元素消亡前的生存时间。指元素自创建日期起至失效时的间隔时间。

上面的表示此缓存最多可以存活1000秒,如果期间超过300秒未访问,那么此缓存失效!

  • memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。默认策略是LRU(最近最少使用),你也可以设置为FIFO(先进先出)或是LFU(较少使用).

注意:defaultCache不管用不用都是必须要配置的。

基本使用

//初始化
// 使用默认配置文件创建CacheManager
//CacheManager manager = CacheManager.create();
CacheManager manager = new CacheManager("src/config/ehcache.xml");
//获取指定Cache对象
Cache configCache = manager.getCache("configCache");
//创建节点对象
Element element = new Element("key1","value1");
//保存节点到configCache
configCache.put(element);
//从configCache获取节点
Element element2 = configCache.getCache("key1");
Object  value = element2.getValue();
//更新节点
configCache.put(new Element("key1","value2"));
//删除节点
configCache.remove("key1");

Spring集成配置

<bean id="cacheManager"
	class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
	<property name="configLocation">
		<value>classpath:ehcache.xml</value>
	</property>
</bean>

<!-- levelOneCache 为在ehcache.xml中定义的Cache -->
<bean id="levelOneCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
	<property name="cacheManager">
		<ref local="cacheManager" />
	</property>
	<property name="cacheName">
		<value>configCache</value>
	</property>
</bean>

利用Spring AOP和Ehcache实现线程级方法缓存

1.拦截器的实现

public class CacheInterceptor implements MethodInterceptor {
	private Cache cache;

	/**
	 * @see  org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();
		String methodName = method.getName();
		Object[] arguments = invocation.getArguments();
		Object result = invocation.proceed();

		String targetName = method.getDeclaringClass().getName();
		String key = getCacheKey(targetName, methodName, arguments);

		Element element = cache.get(key);

		if (element == null) {

			result = invocation.proceed();
			System.out.println("第一次调用方法并缓存其值:" + result);
			cache.put(new Element(key, result));
		} else {
			result = element.getValue();
			System.out.println("从缓存中取得的值为:" + result);
		}
		return result;

	}

	/**
	 * 生成缓存中的KEY值。
	 */
	protected String getCacheKey(String targetName, String methodName, Object[] arguments) {
		StringBuffer sb = new StringBuffer();
		sb.append(targetName).append(".").append(methodName);
		if ((arguments != null) && (arguments.length != 0)) {
			for (int i = 0; i < arguments.length; i++) {
				sb.append(".").append(arguments[i]);
			}
		}
		return sb.toString();
	}

	public void setCache(Cache cache) {
		this.cache = cache;
	}

}

2.配置

<bean id="testService" class="org.mango.cache.ehcache.TestServiceImpl" />

<bean id="serviceMethodInterceptor" class="org.mango.cache.ehcache.CacheInterceptor">
	<property name="cache">
		<ref local="levelOneCache" />
	</property>
</bean>

<bean id="serviceAutoProxyCreator"
	class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<property name="interceptorNames">
		<list>
			<value>serviceMethodInterceptor</value>
		</list>
	</property>
	<property name="beanNames">
		<value>*Service</value>
	</property>
</bean>

集群配置

// todo

Read More

责任

我的源码让猫给吃了=》提供选择,不要找借口! 磁盘跨了–带走了你的所有源码,这不是供应商的错,那是你的错,因为你没有备份。

软件的熵

代码是一种债务! 破窗效应=》不要容忍破窗户!

石头汤

做变化的催化剂=》需求、用户是需要引导的。

DRY

Don’t Repeat Yourself

正交性

消除无关事物之间的影响。 隔离 消除依赖

好处:

  • 提高生产率;
  • 降低风险。

如果显著地改变某个特定功能背后的需求,有多少模块会受到影响?在正交系统中,答案应该是“一个”! 侵入 面向切面编程(AOP) 易于测试

结合DRY原则与正交性原则,你将会发现你开发的系统会变得更为灵活、更易于理解、并且更易于调试、测试和维护!

== 拥抱变化 == 不存在最终决策! 没有人知道未来会怎样!

== 曳光弹vs原型 ==

Read More

简介

SELinux 是透过 MAC 的方式来控管程序,他控制的主体是程序(而并非”用户”), 而控制的目标则是该程序能否操作的”资源”!

运作模式

SELinux 相关定义说明:

  • 主体(Subject): SELinux 主要想要管理的就是程序,因此你可以将”主体”跟本章谈到的”程序”划上等号;

  • 目标(Object): 主体能否操作的”目标”一般就是文档资源。因此这个目标可以与文档资源划上等号;

  • 政策(Policy): 由于程序与文档资源数量庞大,因此 SELinux 会依据某些服务来制订基本的操作政策。这些政策内还会有详细的规则 (rule) 来指定不同的服务开放某些资源的存取与否。在目前的 CentOS 6.x 里面仅提供两个主要的政策如下,一般来说,使用预设 target 政策即可。

  • targeted:针对网络服务限制较多,针对本机限制较少,是预设的政策;

  • mls:完整的 SELinux 限制,限制方面较为严格。

  • 安全性上下文(security context): 主体能不能操作目标除了要符合政策指定之外,主体与目标的”安全性上下文”还必须要一致。 这个”安全性上下文”有点类似文档资源的 rwx .

SELinux 各组件关系

安全性上下文

查看”安全性上下文”

ls -Z

“安全性上下文”主要用冒号分为三个字段

Identify:role:type
身份识别:角色:类型
  • 身份识别: 相当于账号方面的身份识别!主要的身份识别则有底下三种常见的类型:
  • root:表示 root 的账号身份,如同上面的表格显示的是 root 家目录下的数据啊!

  • system_u:表示系统程序方面的识别,通常就是程序啰;

  • user_u:代表的是一般使用者账号相关的身份。

  • 角色: 透过角色字段,我们可以知道这个数据是属于程序、文档资源还是代表使用者。一般的角色有:
  • object_r:代表的是文件或目录等文档资源,这应该是最常见的啰;

  • system_r:代表的就是程序啦!不过,一般使用者也会被指定成为 system_r 喔!

  • 类型: 在预设的 targeted 政策中, Identify 与 Role 字段基本上是不重要的!重要的在于这个类型 (type) 字段! 基本上,一个程序能不能读取到这个文档资源,与类型字段有关!而类型在”主体”与”目标”上的定义是不相同,分别是:
  • type: 在”目标”上”类型”任然为类型;

  • domain: 但在”主体”上它就为领域了!

domain 与 type 需要搭配,主体才能操作目标.

列子:

-rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html

/usr/sbin/httpd 属于 httpd_exec_t 这个可以执行的类型,而 /var/www/html 则属于 httpd_sys_content_t 这个可以让 httpd 领域读取的类型。下图说明了这两者的关系!

SELinux 的 domain 与 type 的关系

上图说明:

  1. 首先,我们触发一个可执行的主体,那就是具有 httpd_exec_t 这个类型的 /usr/sbin/httpd

  2. 该类型会让主体具有 httpd 这个领域,我们的政策针对这个领域已经制定了许多规则,其中包括这个领域可以读取的目标的类型;

  3. 由于 httpd domain 被设定为可以读取 httpd_sys_content_t 这个类型的目标, 因此你的网页放置到 /var/www/html/ 目录下,就能够被 httpd 那支程序所读取了;

  4. 但最终能不能读到正确的资料,还得要看 rwx 是否符合 Linux 权限的规范!

上述的流程告诉我们几个重点: 第一个是政策内需要制订详细的 domain/type 相关性; 第二个是若文档资源的 type 设定错误, 那么即使权限设定为 rwx 全开的 777 ,该程序也无法读取文档资源的啦!

启动与关闭

SELinux 支持三种模式:

  • enforcing: 强制模式,代表 SELinux 运作中,且已经正确的开始限制 domain/type 了;
  • permissive: 宽容模式,代表 SELinux 运作中,不过仅会有警告讯息并不会实际限制 domain/type 的存取.这种模式可以运来作为 SELinux 的 debug 之用;
  • disable: 关闭,SELinux 并没有运行.

    getenforce

可查看当前 SELinux 的模式.

配置文件: /etc/selinux/config

切换模式

setenforce [0|1]

0: permissive

1: enforcing

注意:无法在disable模式下切换.

相关命令

  • chcon

修改 “安全性上下文”类型

chcon [-R] [-t type] [-u user] [-r role] /path/filename
chcon [-R] --reference=/path/templatefile /path/targetfile

选项与参数:

-R :连同该目录下的次目录也同时修改;

-t :后面接”安全性上下文”的类型字段!例如 httpd_sys_content_t ;

-u :后面接身份识别,例如 system_u;

-r :后面街角色,例如 system_r;

–reference=范例文件:拿某个文档当范例来修改后续接的文档的类型!

范例:

chcon -t net_conf_t /tmp/hosts
chcon -t samba_share_t /share
chcon --reference=/var/spool/mail /tmp/hosts
  • restorecon

该命令用来复原 “安全性上下文”类型 的默认值,默认值存储在 /etc/selinux/targeted/contexts

restorecon [-Rv] 文件或目录

选项与参数:

-R :连同次目录一起修改;

-v :将过程显示到屏幕上

  • semanage

“安全性上下文”类型 的历史记录存储在 /etc/selinux/targeted/contexts 中,可以透过 semanage 来查询修改.

semanage {login | user | port | interface | fcontext | translation } -l
semanage fcontext -{a|d|m} [-Nfrst] file_spec

参数说明: fcontext :主要用在”安全性上下文”方面的用途, -l 为查询的意思;

-a :增加的意思,你可以增加一些目录的默认”安全性上下文”类型设定;

-m :修改的意思;

-d :删除的意思。

范例:

semanage fcontext -l | grep '/share'
semanage fcontext -a -t samba_share_t "/share(/.*)?"

增加目录(可以使用正则表达式)的默认”安全性上下文”类型

restorecon -Rv /share

恢复默认值,默认为 samba_share_t

其他工具

查询工具

安装

yum install setools-console

该工具包含 seinfo sesearch 等命令.

  • seinfo

用来查询 SELinux 政策规则

使用

seinfo [-Atrub]

选项与参数:

-A :列出 SELinux 的状态、规则、身份识别、角色、类别等所有信息

-t :列出 SELinux 的所有类别 (type) 种类

-r :列出 SELinux 的所有角色 (role) 种类

-u :列出 SELinux 的所有身份识别 (user) 种类

-b :列出所有规则的种类

范例:

seinfo
seinfo -t | grep samba
  • sesearch

查询详细规则信息

sesearch [-all] [-s 主体类别] [-t 目标类别] [-b 规则种类]

选项与参数:

–all :列出该类别或布尔值的所有相关信息

-t :后面还要接类别,例如 -t httpd_t

-b :后面还要接布尔值的规则,例如 -b httpd_enable_ftp_server

范例:

sesearch --all -t samba_share_t

修改工具

  • getsebool

查询规则的状态(开启/关闭)

getsebool -a [规则种类]

选项与参数:

-a :列出目前系统上面的所有布尔值条款设定为开启或关闭值

  • setsebool

设置规则的状态(开启/关闭)

setsebool [-P] 规则种类=[0|1]

选项与参数:

-P :直接将设定值写入配置文件,永远生效.

日志工具

  • setroubleshoot

当 SELinux 产生错误是,setroubleshoot 会将相关错误信息与解决办法记录到 /var/log/messages/var/log/messages/*

安装

yum install setroubleshoot setroubleshoot-server

安装完后需重启 auditd

/etc/init.d/auditd restart

查询错误信息

cat /var/log/message | grep setroubleshoot

这里查询到的只是摘要信息,要查询详细信息及解决办法,需执行摘要信息提到的 sealart 命令.

sealart -l 6c927892-2469-4fcc-8568-949da0b4cf8d

另外,可以配置 setroubleshoot 将错误信息发送指定的 email.编辑 /etc/setroubleshoot/setroubleshoot.cfg

# 大约在 81 行左右,这行要存在才行!
recipients_filepath = /var/lib/setroubleshoot/email_alert_recipients

# 大约在 147 行左右,将原本的 False 修改成 True 先!
console = True

然后编辑 /var/lib/setroubleshoot/email_alert_recipients 文件,增加 email.

root@localhost
your@email.address

最后重启 auditd


参考:

SELinux 初探

SELinux 管理原则


Read More

安装

yum install samba

开启防火墙

lokkit -s samba

若是 Fedora ubuntu 等请使用 FirewallD 软件进行设置.

添加共享目录

mkdir /share

修改目录的 SELinux 的 Security Context Type

chcon -t samba_share_t /share

编辑配置文件

vi /etc/samba/smb.conf

检查配置文件是否正确

testparm

添加访问用户,该用户必须在系统中存在.

pdbedit -a -u user

修改用户密码

smbpasswd user

重启服务

/etc/init.d/smb restart
或 service smb restart
/etc/init.d/nmb restart
或 service nmb restart

设置开机自启动

chkconfig smb on
chkconfig nmb on

查询共享内容

首先要安装 samba-client

yum install samba-client

再进行查询

smbclient -L //127.0.0.1 -U user%password

挂载

首先要下载安装 cifs-utils

yum install cifs-utils

再进行挂载

mount -t cifs //192.168.1.1/share /mnt/share -o username=user,password=passwd,uid=500,gid=500,dir_mode=0777,file_mode=0777

其中

username,password 为登录用户与密码;

uid,gid 为挂载目录所属用户和组;

dir_mode,file_mode 指定挂载目录的权限.

开机自动挂载

vi /etc/fstab

然后在最末行添加

//ipaddress/share    /mnt/share  cifs    default,username=user,password=passwd    0 0

或者

vi /etc/rc.local

然后添加mount命令:

mount -t cifs //192.168.1.1/share /mnt/share -o username=user,password=passwd,uid=500,gid=500,dir_mode=0777,file_mode=0777

当通过mount.cifs命令对windows下的文件进行映射时,若文件太大,便会产生错误:mount error(12): Cannot allocate memory

解决方法是:

修改注册表 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters\IRPStackSize项的值大于等于15,若IRPStackSize项不存在,就新建一个DWORD值,点击弹出窗口的的进制为十进制,值写个18就ok了,还要重启一下。


Read More

1. 基本命令

1.1. 使用帮助

whatis & info

whatis 查看命令的简要说明,要更详细的信息则使用 info

whatis command

info command

// 正则匹配(适用于只记住部分命令的场合)
whatis -w "loca*"

man

查询命令的详细说明文档。

man command

在man的帮助手册中,将帮助文档分为了9个类别,对于有的关键字可能存在多个类别中,我们就需要指定特定的类别来查看;(一般我们查询bash命令,归类在1类中)

man页面所属的分类标识(常用的是分类1和分类3)

  1. 用户可以操作的命令或者是可执行文件
  2. 系统核心可调用的函数与工具等
  3. 一些常用的函数与数据库
  4. 设备文件的说明
  5. 设置文件或者某些文件的格式
  6. 游戏
  7. 惯例与协议等。例如Linux标准文件系统、网络协议、ASCⅡ,码等说明内容
  8. 系统管理员可用的管理条令
  9. 与内核有关的文件
// 查询特定分类
man 3 printf

根据命令中部分关键字来查询命令

// 在说明文档标题及内容中查询关键字
man -k keyword [keyword...]

// 查找GNOME的config配置工具命令(分类1)
man -k gnome config | grep 1

1.2. 目录和文件处理

mkdir

建立目录.

mkdir dirname

rm

删除文件或目录

// 删除包括子目录在内的目录
rm -r dirname

// 删除非空目录
rm -f dirname

mv

移动(重命名)文件

cp

拷贝文件及目录

cd

更换工作目录.

cd dirname

// 切换到上一个工作目录
cd -

pwd

显示当前工作目录.

ls

列出目录下的内容.

ls -l

// 按时间排序,以列表的方式显示
ls -lrt

// 设置别名(添加进 .bashrc 避免每次手工添加)
alias lsl='ls -lrt'

which

$PATH环境变量中指定的路径来搜索可执行文件所在路径

// 查找make程序安装路径
which make

whereis

查看程序的搜索路径

whereis command | file

当系统中安装了同一软件的多个版本时,不确定使用的是哪个版本时,这个命令就能派上用场。

whereislocate使用同一数据库updatedb

locate

通过索引数据库查询文件(模糊查询)

locate file

// 精确搜索
locate -b "\file"

如果有文件更新,需要定期执行更新命令来更新索引库

updatedb

type

可以用来判断命令是否属于shell内置的

find

实时搜索文件或目录

find ./ -name "core*" | xargs file

// 查找3天前那天发生变化的文件
find / -mtime 3
// 查找3天内发生变化的文件
find / -mtime -3
// 查找3天以前发生变化的文件
find / -mtime +3

// 递归当前目录及子目录删除所有.o文件
find ./ -name "*.o" -exec rm {} \;
  • -exe: 执行命令
  • {}: 占位符,被find替换为当前找到的文件
  • \`: 转义符
  • ;: -exe结束标记

cat

查看文件

cat filename

查看文件

// 查看前10行
head -10 filename

tail

查看文件

// 查看倒数10行
tail -10 filename

more

分页查看文件

egrep

查询文件内容

egrep '03.1\/CO\/AE' TSF_STAT_111130.log.012
egrep 'A_LMCA777:C' TSF_STAT_111130.log.035 > co.out2

chgrp

修改文件的所属组

chown

修改文件的所有者

chown [-R] username[:group] filename

-R 递归修改目录下的多有文件

chmod

修改文件权限

其中:

  • u = owner
  • g = group
  • o = other
  • a = all

例子:

chmod 700 .bashrc

chmod a-x /etc/bashrc

chmod ugo-x .bashrc

chmod -x .bashrc

ln

创建符号链接/硬链接

// 硬连接;删除一个,将文件仍能找到
ln file lnfile

// 符号链接(软链接);删除源,另一个无法使用;
ln -s file lnfile

touch

1.3. 文本处理

grep

xargs

sort

uniq

tr

cut

paste

wc

sed

awk

1.4. 系统管理

时间

  • vi /etc/sysconfig/clock
  • hwclock
  • clock
  • date
  • ntpdate

1.5. 磁盘管理

du

查看目录或文件所占用磁盘空间大小.

// -h 人性化显示
// -s 递归整个目录的大小
du -sh

df

检查文件系统的磁盘空间占有情况.

// -h: human缩写,以易读的方式显示结果
// (即带单位:比如M/G,如果不加这个参数,显示的数字以B为单位)
df -h

dd

fdisk

mkfs

/etc/fstab

mount/umount

mount /dev/dvd /mnt/dvd

2. 用户权限

2.1. 相关文件

/etc/passwd

/etc/shadow

/etc/group

/etc/sudoers

2.2. 基本命令

useradd

添加用户

// 创建相应的帐号和用户目录/home/username
useradd -m username
  • usermod

userdel

删除用户帐号

// -r 选项会同时删除用户目录(/home/username)
userdel -r username

passwd

设置帐号的密码

passwd username
  • groupadd

  • groupmod

  • groupdel

  • gpasswd

sudo

su

帐号切换

// 切换到userB用户帐号工作
su userB

3. 管理监控

who

显示谁登录了系统.

who|w OPTION]

参数说明:

-a, –all : 显示全部

-b, –boot : 登录时间

-H, –heading : 打印列名

-u, –users : 列出登录的用户

top

提供一个当前系统实时的动态视图.默认显示系统中CPU使用率最高的任务,并每5秒刷新一次.

top [选项]

选项说明:

-H : 显示线程信息

-d <时间> : 设置间隔时间

-p <进程号> : 指定进程

-n <次数> : 循环显示的次数

热键说明:

P : 根据CPU使用百分比大小进行排序。

M : 根据驻留内存大小进行排序。

m : 显示内存信息开关.

i : 使top不显示任何闲置或者僵死进程。

t : 显示摘要信息开关.

A : 分类显示系统不同资源的使用大户.有助于快速识别系统中资源消耗多的任务.

f : 添加/删除所要显示的列.

o : 调整所要显示的列的顺序.

r : 调整一个正在运行的进程的 Nice 值.

k : 结束一个正在运行的进程.

c : 切换命令的简称与全称

z : 彩色/黑白显示开关.

vmstat

使用vmstat命令可以得到关于进程、内存、内存分页、堵塞IO、traps及CPU活动的信息。

// n 为监控频率(秒)、m为监控次数
vmstat n m

vmstat 3
// 显示内存使用详细信息
vmstat -m
// 显示内存活动/不活动的信息
vmstat -a

输出列说明:

  • Procs
    • r: 表示运行队列(就是说多少个进程真的分配到CPU),当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。
    • b: 表示阻塞的进程
  • Memory
    • swad: 虚拟内存已使用的大小,如果大于0,表示机器物理内存不足了,单位:KB
    • free: 空闲的物理内存的大小,单位:KB
    • buff: Linux/Unix系统是用来存储目录里面有什么内容,权限等的缓存,单位:KB
    • cache: 缓存我们打开的文件(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高程序执行的性能,程序直接访问内存中的buffer/cached),单位:KB
  • Swap
    • si: 每秒从磁盘读入虚拟内存的大小,单位:KB/秒
    • so: 每秒虚拟内存写入磁盘的大小,单位:KB/秒
  • IO
    • bi: 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,单位:块/秒
    • bo: 块设备每秒发送的块数量,例如读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。单位:块/秒
  • System
    • in: 每秒CPU的中断次数,包括时间中断
    • cs: 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目
  • CPU
    • us: 用户CPU时间
    • sy: 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。
    • id: 空闲 CPU时间,一般来说,id + us + sy = 100

uptime

uptime命令过去只显示系统运行多久。现在,可以显示系统运行多久、当前有多少的用户登录、在过去的1,5,15分钟里平均负载时多少。

ps

显示当前所有运行的程序.

ps [options]

// 查询正在运行的进程信息
ps -ef

// 查询归属于用户colin115的进程
ps -ef | grep colin115
ps -lu colin115

// 以完整的格式显示所有的进程
ps -ajx

pstree

pgrep

查询进程的ID(适合只记得部分进程字段)

// 查询进程名中含有re的进程
pgrep -l re

lsof

list opened files。 作用是列举系统中已经被打开的文件。 在linux环境中,任何事物都是文件,设备是文件,目录是文件,甚至sockets也是文件。

// 查看端口占用的进程状态
lsof -i:3306

// 查看用户username的进程所打开的文件
lsof -u username

// 查询init进程当前打开的文件
lsof -c init

// 查询指定的进程ID(23295)打开的文件
lsof -p 23295

// 查询指定目录下被进程开启的文件(使用+D 递归目录)
lsof +d mydir/

kill

//杀死指定PID的进程 (PID为Process ID)
kill PID

// 杀死相关进程
kill -9 3434

// 杀死job工作 (job为job number)
kill %job

pmap

// 输出进程内存的状况,可以用来分析线程堆栈
pmap PID

sar

可以周期地对 CPU 和内存进行采样。

语法:

sar [options] [<interval> [count]]

选项(options)说明:

  • -A: 所有
  • -u: cpu 利用率
  • -d: 硬盘使用报告
  • -b: I/O 情况
  • -q: 队列
  • -r: 内存使用统计
  • -n: 网络信息统计,需指定关键字如:TCP 等
  • -o: 结果输出到文件

其他参数:

  • interval: 采样周期(秒)
  • count: 采样次数

pidstat

可以监控指定进程及线程的性能情况。 在 sysstat 工具包中。

安装:

yum install sysstat

参数说明:

-p: 指定进程 ID -u: 对 cpu 进行监控 -d: 对 I/O 进行监控 -r: 对内存进行监控 -t: 监控细化到线程

free

显示内存使用情况.

free [options]

参数说明:

-t, –total : 显示合计行.

-m : 显示内存使用量.

5. 网络安全

5.1. 设置

所有网络配置完成后,都需要重启网络服务:

service network restart 或/etc/init.d/network restart

网卡配置

网卡配置文件位于 /etc/sysconfig/network-scripts 目录下。 一块网卡对应一个网卡配置文件,配置文件命名规则:

ifcfg-网卡类型+网卡的序列号

由于以太网卡类型是eth,网卡的序列号从0开始,所以第一块网卡的配置文件名称为ifcfg-eth0,第二块网卡为ifcfg-eth1,以此类推。

DEVICE=eth0 #物理设备名
TYPE=Ethernet #网卡的类型
HWADDR=00:02:B3:0B:64:22 #该网卡的MAC地址
IPADDR=192.168.1.10 #IP地址
NETMASK=255.255.255.0 #掩码值
NETWORK=192.168.1.0 #网络地址(可不要)
BROADCAST=192.168.1.255 #广播地址(可不要)
GATEWAY=192.168.1.1 #网关地址
ONBOOT=yes # [yes|no](启动时是否激活设备)
USERCTL=no #[yes|no](非root用户是否可以控制该设备)
BOOTPROTO=static #[none|static|bootp|dhcp](引导时不使用协议|静态分配|BOOTP协议|DHCP协议)

DNS 配置

配置文件位于 /etc/resolv.conf

nameserver 202.109.14.5 #主DNS
nameserver 219.141.136.10 #次DNS
search localdomain

ifconfig 命令

ifconfig eth0 192.168.0.10 将采用默认子网掩码
ifconfig eth0 192.168.0.10 netmask 255.255.255.252 (手动定义子网掩码)
ifconfig eth0 up(激活网卡)
ifconfig eth0 down(关闭网卡)

route 命令

route add -net 192.168.1.0 netmask 255.255.255.0 eth0 (添加一条到192.168.1.0网络的路由条目)
route del -net 192.168.1.0 netmask 255.255.255.0 (删除路由条目)
route -C 查看缓冲表
route -n 查看本地路由表

其他配置文件

/etc/hosts(本地主机ip地址映射,可以有多个别名)。

/etc/services(端口号与标准服务之间的对应关系)。

/etc/sysconfig/network(设置主机名,网关,域名)。

HOSTANME=zjw.com(主机名)(需要重启计算机才有效)
GATEWAY=192.168.1.1(网关)

5.2. 常用命令

netstat

用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。

// 列出所有端口 (包括监听和未监听的)
netstat -a
// 列出所有 tcp 端口
netstat -at
// 列出所有有监听的服务状态
netstat -l

netstat -antp

traceroute

路由跟踪

traceroute IP

host

// DNS查询,寻找域名domain对应的IP
host domain
//  反向DNS查询
host IP

wget

选项:

  • –limit-rate : 下载限速
  • -o : 指定日志文件
  • -c : 断点续传

    // 直接下载文件或者网页 wget url

ssh

// ssh登陆远程服务器hostname,id为用户名
ssh id@hostname

sftp

ftp/sftp文件传输

// 登陆服务器host,id为用户名
sftp id@host

sftp登陆后,可以使用下面的命令进一步操作:

get filename # 下载文件
put filename # 上传文件
ls # 列出host上当前路径的所有文件
cd # 在host上更改当前路径
lls # 列出本地主机上当前路径的所有文件
lcd # 在本地主机更改当前路径

scp

ssh协议下的网络复制

// 将本地localpath指向的文件上传到远程主机的path路径
scp localpath id@host:path
// 遍历下载path路径下的整个文件系统,到本地的localpath
scp -r id@host:path localpath

6. Other

rpm

执行安装包。 分二进制包(Binary)以及源代码包(Source)两种。二进制包可以直接安装在计算机中,而源代码包将会由RPM自动编译、安装。源代码包经常以src.rpm作为后缀名。

参数说明:

-i,–install : 安装

-v,–verbose : 显示详细信息

-e,–erase : 卸载

-q : 查询

-a,–all : 查询/检验所有包

–nodeps : 忽略包依赖关系强行安装

范例:

rpm -q samba
rpm -qa | grep httpd
rpm -ql httpd

dpkg

tree

打包/解包/压缩/解压缩

tar

打包/解包

tar [必要参数] [选择参数] [文件]

参数说明:

  • -c : 建立新的归档文件
  • -f : 指定文件
  • -t : 显示打包文件的内容
  • -x : 从打包文件中提取文件
  • -v : 显示操作过程
  • -j : 使用bz2压缩算法解/压文件
  • -J : 使用xz压缩算法解/压文件
  • -z : 使用gz压缩算法解/压文件

压缩比: gz < bz2 < xz ; 压缩速度: gz > bz2 > xz 。

范例:

# 将文件 foo 和 bar 打包为 archive.tar
tar -cf archive.tar foo bar

# 显示 archive.tar 中的所有文件
tar -tvf archive.tar

# 解包 archive.tar
tar -xf archive.tar

# 解压bz2
tar -jxvf demo.tar.bz2

# 如果tar 不支持j,应使用bzip2来解压,再使用tar解包
# -d decompose,解压缩
bzip2 -d  demo.tar.bz2
tar -xvf  demo.tar

gzip

压缩

gzip demo.txt
// 生成 demo.txt.gz

gunzip

解压缩

gunzip demo.txt.gz

dump & restore

cpio

多任务

jobs

nohup

nohup [命令与参数] &

at

执行一次性计划任务

at 10:00 tomorrow

然后在at>提示符处输入要执行的命令。 最后按Ctrl+D来保存。 可以使用<输入重定向来输入命令。

相关目录文件

/etc/at.deny

该文件中所列的用户不允许使用 at 命令.

/etc/at.allow

该文件中所列的用户允许使用 at 命令. *.deny*.allow文件不能同时存在。

crontab

crond 是 linux 用来定期执行程序的命令。 当安装完成操作系统之后,默认便会启动此任务调度命令。 crond 命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。

linux 任务调度的工作主要分为以下两类:

  1. 系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存;

  2. 个人执行的工作:某个用户定期要做的工作,例如每隔10分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置.

相关目录文件

/etc/cron.deny

该文件中所列的用户不允许使用 Crontab 命令。

/etc/cron.allow

该文件中所列的用户允许使用 Crontab 命令。 *.deny*.allow文件不能同时存在。

/var/spool/cron/

是所有用户的 crontab 文件.

命令格式

crontab [ -u user ] file
crontab [ -u user ] { -l | -r | -e } [-i] [-s]

参数含义:

-u user : 设置指定用户 user 的调度内容.不使用时,默认当前用户.

file : 将所有的 Crontab 文件的内容先存放在 file 中,再用 crontab file 的方式来设置调度。

-l : 显示用户的 Crontab 文件的内容.

-i : 删除用户的 Crontab 文件前给提示

-r : 从 Crontab 目录中删除用户的 Crontab 文件.

-e : 编辑用户的 Crontab 文件.默认为 vi,可以通过以下命令更改:

EDITOR=vi
export EDITOR

Crontab 文件内容格式如下:

f1 f2 f3 f4 f5 [用户名] program

用户名用于指定命令以何种身份执行.

其中 f1 是表示分钟(0-59),f2 表示小时(0-23),f3 表示一个月份中的第几日(0-31),f4 表示月份(1-12),f5 表示一个星期中的第几天(0-7,0,7都表示星期天)。program 表示要执行的程序。

当 f1 为 * 时表示每分钟都要执行 program,f2 为 * 时表示每小时都要执行程序,其余类推.

当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,f2 为 a-b 时表示从第 a 到第 b 小时都要执行,其余类推.

当 f1 为 */n 时表示每间隔 n 分钟执行一次,f2 为 */n 表示每间隔 n 小时执行一次,其余类推.

当 f1 为 a, b, c,… 时表示第 a, b, c,… 分钟要执行,f2 为 a, b, c,… 时表示第 a, b, c…个小时要执行,其余类推.

例子 :

每月每天上午7点的第 0 分钟执行一次 /bin/ls :

0 7 * * * /bin/ls

在 12 月内, 每天的早上 6 点到 12 点中,每隔 3 分钟执行一次 /usr/bin/backup :

0 6-12/3 * 12 * /usr/bin/backup

周一到周五每天下午 5:00 寄一封信给 alex@domain.name :

0 17 * * 1-5 mail -s "hi" alex@domain.name  /dev/null 2>&1

守护进程

createrepo

用于生成 yum 仓库所必须的一些信息,这些信息都存放在 repodata/ 目录底下

createrepo /path/packages

yum

apt-*


参考

Linux基础

鸟哥的Linux私房菜

Linux 命令行

Linux就是这个范儿

Read More

安装

CentOS 6

下载和安装

wget https://downloads-packages.s3.amazonaws.com/centos-6.5/gitlab-7.0.0_omnibus-1.el6.x86_64.rpm
sudo yum install openssh-server
sudo yum install postfix # Select 'Internet Site', using sendmail or exim is also OK
sudo rpm -i gitlab-7.0.0_omnibus-1.el6.x86_64.rpm

开启防火墙

sudo lokkit -s http -s ssh

编辑配置文件

sudo vi /etc/gitlab/gitlab.rb

初始化配置

sudo gitlab-ctl reconfigure

检查运行情况

sudo gitlab-ctl status

初始化用户和密码

  • username:root

  • password:5iveL!fe

卸载

sudo gitlab-ctl uninstall
sudo rpm -e gitlab

目录结构

  • /opt/gitlab Gitlab 的应用程序代码和依赖都存放在此.
  • /var/opt/gitlab Gitlab-ctl reconfigure 将配置文件以及应用程序数据保存在这里.
  • /etc/gitlab Gitlab 应用程序的配置文件存放在这里. These are the only files that you should ever have to edit manually.
  • /var/log/gitlab Gitlab 的所有日志都存放在这里.

启动与停止

启动

sudo gitlab-ctl start

停止服务

sudo gitlab-ctl stop

重启

sudo gitlab-ctl restart

备份

运行以下命令:

sudo gitlab-rake gitlab:backup:create

该命令将在 /var/opt/gitlab/backups 目录下创建一个 tar 的备份文件.备份文件名类似 1393513186_gitlab_backup.tar,其中 1393513186 是时间戳.

定时备份

sudo su -
crontab -e

然后编辑该文件:

0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create

每天凌晨2点进行备份.

恢复备份

首先保证备份文件存在于 /var/opt/gitlab/backups 目录下. 然后指定你要恢复的备份文件的时间戳.

# Stop processes that are connected to the database
sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq

# This command will overwrite the contents of your GitLab database!
sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186

# Start GitLab
sudo gitlab-ctl start

配置

Gitlab 几乎都是通过编辑文件 /etc/gitlab/gitlab.rb 来进行配置的.修改完该文件后必须运行 gitlab-ctl reconfigure 来变更确认新配置.

gitlab.rb 与 其他配置文件的对应

例如:

gitlab.yml 文件中有如下配置

production: &base
  gitlab:
	default_projects_limit: 10

转换为 gitlab.rb 时为

gitlab_rails['gitlab_default_projects_limit'] = 10

又如:

修改备份目录以及备份保存时间

gitlab_rails['backup_path'] = "/mnt/gitlab/backups"
gitlab_rails['backup_keep_time'] = 604800	#(备份保留7天)

URL

编辑文件 /etc/gitlab/gitlab.rb

external_url "http://gitlab.example.com"

更改 git 的数据存放路径

编辑文件 /etc/gitlab/gitlab.rb

git_data_dir "mnt/nas/git-data"

更改路径后的数据迁移问题参见备份

LDAP

HTTPS

编辑文件 /etc/gitlab/gitlab.rb

external_url "https://gitlab.example.com"
nginx['redirect_http_to_https'] = true

更改端口

增加默认ssl证书

email / SMTP

gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.server"
gitlab_rails['smtp_port'] = 456
gitlab_rails['smtp_user_name'] = "smtp user"
gitlab_rails['smtp_password'] = "smtp password"
gitlab_rails['smtp_domain'] = "example.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true

日志

# Tail all logs; press Ctrl-C to exit
sudo gitlab-ctl tail

# Drill down to a sub-directory of /var/log/gitlab
sudo gitlab-ctl tail gitlab-rails

# Drill down to an individual file
sudo gitlab-ctl tail nginx/gitlab_error.log

数据库

相关错误处理

无法使用 ssh 进行 push

提示输入 git@serverip 的密码。

使用 ssh -vT git@serverip 出现如下提示:

 Next authentication method: password

处理办法:

使用 setroubleshoot 查询出错信息,然后根据提示处理.

semanage fcontext -a -t ssh_home_t '/home/git/.ssh(/.*)?'
restorecon -Rv /home/git/.ssh

参考

Gitlab Omnibus Readme


Read More

yum

常用操作

yum search someword

yum list|grouplist packagename [installed]

yum install packagename

yum erase|remove packagename

downloadonly 插件

  • 安装

该插件用于下载 yum 里的软件安装。 最新的版本已内置该插件,无需安装。

# 较旧的版本
yum install yum-downloadonly

# 较新的版本
yum install yum-plugin-doenloadonly
  • 配置

/etc/yum/pluginconf.d/downloadonly.conf 文件。

  • 使用

    yum install –downloadonly –downloaddir=./path packagename

查询相关 locate/which/whereis/find/grep

  • 安装

    yum install mlocate which grep

防火墙相关 lokkit/iptables

例子:

sudo lokkit -s http -s ssh
sudo lokkit -p 2443:tcp

genisoimage / mkisofs

genisoimage [参数] [-o isofile] pathspec [pathspec ...]

参数说明:

-o : 指定映像文件名称

-r : 使用Rock Ridge Extensions(支持文件名字母大小写、符号字符以及长文件名),并开放全部文件的读取权限。

-J : 使用Joliet格式(可显示 64个字符 ,并可使用中文,但是不能被MAC机所读取)的目录与文件名称。

git-cvs

cvs 迁移至 git 工具.

安装

yum install git-cvs

设置 CVSROOT 并登录

export CVSROOT=pserver:username@serverip:/home/cvs
cvs login

导出

git cvsimport -v project_name -C project_name

参数说明

-v : 显示详细信息.

-C : 到处目录名称,没有则新建.

-d : CVSROOT

乱码问题

vi /etc/sysconfig/i18n

将编码转成 cvs 服务器的编码,然后同时将终端编码(putty等)的编码也转换成相同编码.

ffmpeg/mencoder

音视频转换工具。

安装:

yum install ffmpeg libvpx
yum install mencoder

使用:

ffmpeg -i /path/video.vob /path/video.avi

Read More

简介

项目主页: http://junit.org/

JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中为最成功的一个。 JUnit有它自己的JUnit扩展生态圈。

多数Java的开发环境都已经集成了JUnit作为单元测试的工具。

使用

public class Example {
	File output;
	@Before
	public void createOutputFile() {
		  output= new File(...);
	}
	@Test
	public void something() {
		  ...
	}
	@After
	public void deleteOutputFile() {
		  output.delete();
	}
}

注解说明

@Before:

使用了该元数据的方法在每个测试方法执行之前都要执行一次。

@After:

使用了该元数据的方法在每个测试方法执行之后要执行一次。

注意:@Before@After 标示的方法只能各有一个。 这个相当于取代了JUnit以前版本中的 setUptearDown 方法,当然你还可以继续叫这个名字,不过JUnit不会霸道的要求你这么做了。

@Test(expected=*.class)

在JUnit4.0之前,对错误的测试,我们只能通过 fail 来产生一个错误,并在try块里面 assertTrue(true) 来测试。现在,通过 @Test 元数据中的 expected 属性。expected 属性的值是一个异常的类型

@Test(timeout=xxx):

该元数据传入了一个时间(毫秒)给测试方法,

如果测试方法在制定的时间之内没有运行完,则测试也失败。

@ignore:

该元数据标记的测试方法在测试中会被忽略。 当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库链接,而在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。 同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。 比如:@ignore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

@BeforeClass 和 @AfterClas :

只在测试用例初始化时执行 @BeforeClass 方法,当所有测试执行完毕之后,执行 @AfterClass 进行收尾工作。 在这里要注意一下,每个测试类只能有一个方法被标注为 @BeforeClass@AfterClass,并且该方法必须是 PublicStatic 的。

@RunWith :

@RunWith 是用来修饰类的,而不是用来修饰函数的.指定使用哪个Runer运行测试. 以下是常用的Runer.

  • @RunWith(Parameterized.class) : 参数化测试.用 @Parameters 标注测试数据的集合.

  • @RunWith(Suite.class) : 打包测试,将所有需要运行的测试类集中起来,一次性的运行完毕. 同时还需要另外一个标注 @Suite.SuiteClasses,来表明这个类是一个打包测试类。 我们把需要打包的类作为参数传递给该标注就可以了。


参考

项目文档


Read More