本文的目的是介绍Linuxdockersvn的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于Cannotcheckoutfromsvn:Cannotrunprogram"
本文的目的是介绍Linux docker svn的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于Cannot checkout from svn: Cannot run program "svn"、Centos7 搭建 SVN+Apache+iF.SVNAdmin 实现 web 管理 SVN、cJson --svn:cjson.svn.sourceforge.net/svnroot/c...、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock的知识。
本文目录一览:- Linux docker svn
- Cannot checkout from svn: Cannot run program "svn"
- Centos7 搭建 SVN+Apache+iF.SVNAdmin 实现 web 管理 SVN
- cJson --svn:cjson.svn.sourceforge.net/svnroot/c...
- Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock
Linux docker svn
1. 获取 svn 镜像
docker search svn
docker pull docker.io/garethflowers/svn-server
docker images
2. 创建 svn 容器,挂载 svn 目录,避免删除容器时内容丢失,svn 端口默认为 3690
docker run -v /home/svn:/var/opt/svn/ --name svn -p 3690:3690 --privileged=true -e SVN_REPONAME=ProjectName -d docker.io/garethflowers/svn-server
注:SVN_REPONAME 用于指定新创建的项目的名称
3. 进入 svn 容器
docker exec -it svn /bin/sh
4. 创建项目名称
svnadmin create /var/opt/svn/ProjectName
注:ProjectName 为自定义项目名称,如果创建 docker 时已给出 SVN_REPONAME,可省略改语句
5. 进入项目目录
cd /var/opt/svn/ProjectName/conf
注:ProjectName 为自定义项目名称
6. 查看文件
ls
7. 编辑配置(使用 svn 时若 show log 无法查看日志则修改 anon-access = read,将 read 修改为 none)
vi svnserve.conf
删除前面的 # 号
anon-access = read
auth-access = write
password-db = passwd
authz-db = authz
8. 编辑用户
vi passwd
在 [users] 中新增用户
UserName = UserPass
9. 编辑用户组和权限
vi authz
在 [groups] 中新增用户组
GroupName = UserName
新增授权
[/]
@GroupName = rw
注:[/] 默认为根目录下所有资源,如果要限定授权就增加子目录
[ProjectName:/]
@GroupName = rw
10. 退出容器并重启 svn docker
exit
docker restart svn
Cannot checkout from svn: Cannot run program "svn"
IntelliJ IDEA 13.1.2安装后,SVN checkout时候会出现如下错误:
Cannot load supported formats: Cannot run program "svn": CreateProcess error=2, μ
究其原因,是SVN使用了命令行工具,如果本地没有SVN的命令行工具,则导致出错。
解决办法:
1、安装客户端
http://ncu.dl.sourceforge.net/project/tortoisesvn/1.8.7/Application/TortoiseSVN-1.8.7.25475-x64-svn-1.8.9.msi
http://jaist.dl.sourceforge.net/project/tortoisesvn/1.8.7/Language%20Packs/LanguagePack_1.8.7.25475-x64-zh_CN.msi
注意:安装时候必须选中command line 。。。这个选项。
2、完成后配置IDEA
这样,问题彻底解决!
Centos7 搭建 SVN+Apache+iF.SVNAdmin 实现 web 管理 SVN
介绍
因为使用命令方式管理太麻烦了,自己用还好,如果突然增加很多人呢?那么就可以使用 iF.SVNAdmin 来管理 SVN.
iF.SVNAdmin 可以使用户使用 http 可视化的操作 svn 服务器,管理 svn 服务器.
安装相关软件
1. 安装 Apache
yum -y install httpd
2. 安装 svn 服务器和 mod_dav_svn (mod_dav_svn 是 apache 服务器访问 svn 的一个模块)
yum -y install httpd
3. 测试是否安装成功
[root@zh ~]# svnserve --version
svnserve,版本 1.7.14 (r1542130)
编译于 Apr 11 2018,02:40:28
版权所有 (C) 2013 Apache 软件基金会。
此软件包含了许多人的贡献,请查看文件 NOTICE 以获得更多信息
本文分享 CSDN - TrueDei。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。
cJson --svn:cjson.svn.sourceforge.net/svnroot/c...
//cJson.h
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item''s string, if type==cJSON_String */
int valueint; /* The item''s number, if type==cJSON_Number */
double valuedouble; /* The item''s number, if type==cJSON_Number */
char *string; /* The item''s name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You''ll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr();
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull();
extern cJSON *cJSON_CreateTrue();
extern cJSON *cJSON_CreateFalse();
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray();
extern cJSON *cJSON_CreateObject();
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don''t want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
#ifdef __cplusplus
}
#endif
#endif
//cjson.cpp
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* cJSON */
/* JSON parser in C. */
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"
static const char *ep;
const char *cJSON_GetErrorPtr() {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item()
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}
/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
/* Could use sscanf for this? */
if (*num==''-'') sign=-1,num++; /* Has sign? */
if (*num==''0'') num++; /* is zero */
if (*num>=''1'' && *num<=''9'') do n=(n*10.0)+(*num++ -''0''); while (*num>=''0'' && *num<=''9''); /* Number? */
if (*num==''.'' && num[1]>=''0'' && num[1]<=''9'') {num++; do n=(n*10.0)+(*num++ -''0''),scale--; while (*num>=''0'' && *num<=''9'');} /* Fractional part? */
if (*num==''e'' || *num==''E'') /* Exponent? */
{ num++;if (*num==''+'') num++; else if (*num==''-'') signsubscale=-1,num++; /* With sign? */
while (*num>=''0'' && *num<=''9'') subscale=(subscale*10)+(*num++ - ''0''); /* Number? */
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item)
{
char *str;
double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!=''\"'') {ep=str;return 0;} /* not a string! */
while (*ptr!=''\"'' && *ptr && ++len) if (*ptr++ == ''\\'') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!=''\"'' && *ptr)
{
if (*ptr!=''\\'') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case ''b'': *ptr2++=''\b''; break;
case ''f'': *ptr2++=''\f''; break;
case ''n'': *ptr2++=''\n''; break;
case ''r'': *ptr2++=''\r''; break;
case ''t'': *ptr2++=''\t''; break;
case ''u'': /* transcode utf16 to utf8. */
sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid.
if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs.
{
if (ptr[1]!=''\\'' || ptr[2]!=''u'') break; // missing second-half of surrogate.
sscanf(ptr+3,"%4x",&uc2);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate.
uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr==''\"'') ptr++;
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str)
{
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
*ptr2++=''\"'';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!=''\"'' && *ptr!=''\\'') *ptr2++=*ptr++;
else
{
*ptr2++=''\\'';
switch (token=*ptr++)
{
case ''\\'': *ptr2++=''\\''; break;
case ''\"'': *ptr2++=''\"''; break;
case ''\b'': *ptr2++=''b''; break;
case ''\f'': *ptr2++=''f''; break;
case ''\n'': *ptr2++=''n''; break;
case ''\r'': *ptr2++=''r''; break;
case ''\t'': *ptr2++=''t''; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++=''\"'';*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt);
/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
/* Parse an object - create a new root, and populate. */
cJSON *cJSON_Parse(const char *value)
{
cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */
if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
return c;
}
/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value==''\"'') { return parse_string(item,value); }
if (*value==''-'' || (*value>=''0'' && *value<=''9'')) { return parse_number(item,value); }
if (*value==''['') { return parse_array(item,value); }
if (*value==''{'') { return parse_object(item,value); }
ep=value;return 0; /* failure. */
}
/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt)
{
char *out=0;
if (!item) return 0;
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item);break;
case cJSON_String: out=print_string(item);break;
case cJSON_Array: out=print_array(item,depth,fmt);break;
case cJSON_Object: out=print_object(item,depth,fmt);break;
}
return out;
}
/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{
cJSON *child;
if (*value!=''['') {ep=value;return 0;} /* not an array! */
item->type=cJSON_Array;
value=skip(value+1);
if (*value=='']'') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value=='','')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; /* memory fail */
}
if (*value=='']'') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn''t fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
/* Compose the output array. */
*out=''['';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) {*ptr++='','';if(fmt)*ptr++='' '';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++='']'';*ptr++=0;
return out;
}
/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{
cJSON *child;
if (*value!=''{'') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object;
value=skip(value+1);
if (*value==''}'') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!='':'') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value=='','')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!='':'') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value==''}'') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string);
entries[i++]=ret=print_value(child,depth,fmt);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
return 0;
}
/* Compose the output: */
*out=''{'';ptr=out+1;if (fmt)*ptr++=''\n'';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++=''\t'';
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
*ptr++='':'';if (fmt) *ptr++=''\t'';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++='','';
if (fmt) *ptr++=''\n'';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++=''\t'';
*ptr++=''}'';*ptr++=0;
return out;
}
/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
/* Replace array/object items with new ones. */
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
/* Create basic types: */
cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock
在 Docker 容器里面使用 docker run
/docker build
?
Docker 容器技术目前是微服务/持续集成/持续交付领域的第一选择。而在 DevOps 中,我们需要将各种后端/前端的测试/构建环境打包成 Docker 镜像,然后在需要的时候,Jenkins 会使用这些镜像启动容器以执行 Jenkins 任务。
为了方便维护,我们的 CI 系统如 Jenkins,也会使用 Docker 方式部署。 Jenkins 任务中有些任务需要将微服务构建成 Docker 镜像,然后推送到 Harbor 私有仓库中。 或者我们所有的 Jenkins Master 镜像和 Jenkins Slave 镜像本身都不包含任何额外的构建环境,执行任务时都需要启动包含对应环境的镜像来执行任务。
我们的 Jenkins Master、Jenkins Slaves 都是跑在容器里面的,该如何在这些容器里面调用 docker run
命令启动包含 CI 环境的镜像呢? 在这些 CI 镜像里面,我们从源码编译完成后,又如何通过 docker build
将编译结果打包成 Docker 镜像,然后推送到内网仓库呢?
答案下面揭晓。
一、原理说明:/var/run/docker.sock
Docker 采取的是 Client/Server 架构,我们常用的 docker xxx
命令工具,只是 docker 的 client,我们通过该命令行执行命令时,实际上是在通过 client 与 docker engine 通信。
我们通过 apt/yum 安装 docker-ce 时,会自动生成一个 systemd 的 service,所以安装完成后,需要通过 sudo systemctl enable docker.service
来启用该服务。 这个 Docker 服务启动的,就是 docker engine,查看 /usr/lib/systemd/system/docker.service
,能看到有这样一条语句:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
默认情况下,Docker守护进程会生成一个 socket(/var/run/docker.sock
)文件来进行本地进程通信,因此只能在本地使用 docker 客户端或者使用 Docker API 进行操作。 sock 文件是 UNIX 域套接字,它可以通过文件系统(而非网络地址)进行寻址和访问。
因此只要以数据卷的形式将 docker 客户端和上述 socket 套接字挂载到容器内部,就能实现 "Docker in Docker",在容器内使用 docker 命令了。具体的命令见后面的「示例」部分。
要记住的是,真正执行我们的 docker 命令的是 docker engine,而这个 engine 跑在宿主机上。所以这并不是真正的 "Docker in Docker".
二、示例
在容器内部使用宿主机的 docker,方法有二:
- 命令行方式:将
/usr/bin/docker
映射进容器内部,然后直接在容器内部使用这个命令行工具docker
- 需要的时候,也可以将
/etc/docker
文件夹映射到容器内,这样容器内的docker
命令行工具也会使用与宿主机同样的配置。
- 需要的时候,也可以将
- 编程方式:在容器内部以编程的方式使用 docker
- 通过 python 使用 docker: 在 Dockerfile 中通过
pip install docker
将 docker client 安装到镜像中来使用
- 通过 python 使用 docker: 在 Dockerfile 中通过
容器的启动方式也有两种,如下:
1. 直接通过 docker 命令启动
示例命令如下:
docker run --name <name> \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
--user root \
<image-name>:<tag>
**必须以 root 用户启动!(或者其他有权限读写 /var/run/docker.sock
的用户)**然后,在容器内就能正常使用 docker 命令,或者访问宿主机的 docker api 了。
2. 使用 docker-compose 启动
docker-compose.yml 文件内容如下:
version: ''3.3''
services:
jenkins-master:
image: jenkinsci/blueocean:latest
container_name: jenkins-master
environment:
- TZ=Asia/Shanghai # 时区
ports:
- "8080:8080"
- "50000:50000"
volumes:
- ./jenkins_home:/var/jenkins_home # 将容器中的数据映射到宿主机
- /usr/bin/docker:/usr/bin/docker # 为容器内部提供 docker 命令行工具(这个随意)
- /var/run/docker.sock:/var/run/docker.sock # 容器内部通过 unix socket 使用宿主机 docker engine
user: root # 必须确保容器以 root 用户启动!(这样它才有权限读写 docker.socket)
restart: always
然后通过 docker-compose up -d
即可后台启动容器。
Docker 中的 uid 与 gid
通过上面的操作,我们在容器内执行 docker ps
时,还是很可能会遇到一个问题:权限问题。
如果你容器的默认用户是 root,那么你不会遇到这个问题,因为 /var/run/docker.sock
的 onwer 就是 root.
但是一般来说,为了限制用户的权限,容器的默认用户一般都是 uid 和 gid 都是 1000 的普通用户。这样我们就没有权限访问 /var/run/docker.sock
了。
解决办法:
方法一(不一定有效):在构建镜像时,最后一层添加如下内容:
# docker 用户组的 id,通常都是 999
RUN groupadd -g 999 docker \
&& usermod -aG docker <your_user_name>
这样我们的默认用户,就能使用 docker 命令了。
P.S.
999
不一定是 docker 用户组,所以上述方法某些情况下可能失效。这时还是老老实实通过docker run -u root
启动容器吧。(或者在docker-compose.yml
中添加user: root
属性)
参考
- Docker in Docker - 王柏元
关于Linux docker svn的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Cannot checkout from svn: Cannot run program "svn"、Centos7 搭建 SVN+Apache+iF.SVNAdmin 实现 web 管理 SVN、cJson --svn:cjson.svn.sourceforge.net/svnroot/c...、Docker in Docker(实际上是 Docker outside Docker): /var/run/docker.sock等相关内容,可以在本站寻找。
本文标签: