docker의 cli는 매개 변수를 어떻게 설명합니까

5433 단어
이어서 지난 docker 명령attach 원본 분석을 하고 계속 가세요
먼저 prase의 전체 코드를 보십시오:
//  docker attach XXXID -> XXXID = arguments
func (fs *FlagSet) Parse(arguments []string) error {
	fs.parsed = true 
	//   ,  :Parsed reports whether fs.Parse has been called,         
	fs.args = arguments 
	for {
		seen, name, err := fs.parseOne()
		//     parseOne     ,seen  true   
		if seen {
			continue
		}
		if err == nil {
			break
		}
		if err == ErrRetry {
			if len(name) > 1 {
				err = nil
				//strings.Split("123","")="1 2 3" , string       {1,2,3}
				for _, letter := range strings.Split(name, "") {
					fs.args = append([]string{"-" + letter}, fs.args...)
					//    "-",  parseOne
					seen2, _, err2 := fs.parseOne()
					if seen2 {
						continue
					}
					if err2 != nil {
					err = fs.failf("flag provided but not defined: -%s", name)
						break
					}
				}
				if err == nil {
					continue
				}
			} else {
				err = fs.failf("flag provided but not defined: -%s", name)
			}
		}
		switch fs.errorHandling {
		case ContinueOnError:
			return err
		case ExitOnError:
			os.Exit(2)
		case PanicOnError:
			panic(err)
		}
	}
	return nil
}

Prase의 함수를 보면 구체적으로 집행하는 관건적인 절차는 소위 PraseOne 함수이다. 이 함수를 함께 살펴보자.
func (fs *FlagSet) parseOne() (bool, string, error) {
	if len(fs.args) == 0 {
		return false, "", nil
	}
	//         arguments []string,string  ,s      
	s := fs.args[0]
	
	//  docker attach           ContainerID,s[0]!='-',   
	//   ,   parse,    nil,           check   flagset     
	
	if len(s) == 0 || s[0] != '-' || len(s) == 1 {
		return false, "", nil
	}
	
	
	if s[1] == '-' && len(s) == 2 { // "--" terminates the flags
		fs.args = fs.args[1:]
		return false, "", nil
	}
	
	//        '-'   name
	name := s[1:]
	if len(name) == 0 || name[0] == '=' {
		return false, "", fs.failf("bad flag syntax: %s", s)
	}

	//       
	fs.args = fs.args[1:]
	hasValue := false
	value := ""
	//  "="   ,     
	if i := strings.Index(name, "="); i != -1 {
		value = trimQuotes(name[i+1:]) //"="    value
		hasValue = true
		name = name[:i] // "="      name
	}
        //  args = --log-driver=json-file  name = -log-driver value =json-file
	
	m := fs.formal
	flag, alreadythere := m[name] // map  ,      
	//  attach  ,fs.formal   name  nostdin sig-proxy,    
	
	if !alreadythere {
		if name == "-help" || name == "help" || name == "h" { 
		// special case for nice help message.
			fs.usage()
			return false, "", ErrHelp
		}
		if len(name) > 0 && name[0] == '-' {
			return false, "", fs.failf("flag provided but not defined: -%s", name)
		}
		return false, name, ErrRetry
	}
	//Bool      ,hasValue     "="     
	if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { 
	// special case: doesn't need an arg
		if hasValue {
		        //    flag  
			if err := fv.Set(value); err != nil {
	return false, "", fs.failf("invalid boolean value %q for  -%s: %v", value, name, err)
			}
		} else {
			fv.Set("true")
		}
	} else {
		// It must have a value, which might be the next argument.
		if !hasValue && len(fs.args) > 0 {
			// value is the next arg //    "=" value       
			hasValue = true
			value, fs.args = fs.args[0], fs.args[1:]
		}
		if !hasValue {
			return false, "", fs.failf("flag needs an argument: -%s", name)
		}
		//   Bool flag  
		if err := flag.Value.Set(value); err != nil {
		return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err)
		}
	}
	if fs.actual == nil {
		fs.actual = make(map[string]*Flag)
	}
	fs.actual[name] = flag //      fs.actual 
	//                     ,   
	for i, n := range flag.Names {
		if n == fmt.Sprintf("#%s", name) {
			replacement := ""
			for j := i; j < len(flag.Names); j++ {
				if flag.Names[j][0] != '#' {
					replacement = flag.Names[j]
					break
				}
			}
			if replacement != "" {
                            fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced                                 by '-%s' soon. See usage.
", name, replacement) } else { fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be remo                                ved soon. See usage.
", name) } } } return true, "", nil }

이 가운데 뭐가 빠졌는지 기억나?당연히 flag의 set은 어떻게 이루어졌나요?
//Flag Value        interface,       String Set  ,              
type Value interface {
	String() string
	Set(string) error
}
// -- bool Value
type boolValue bool

func newBoolValue(val bool, p *bool) *boolValue {
	*p = val
	return (*boolValue)(p)
}

//  golang           ,  Set  ,    Value     ,      
func (b *boolValue) Set(s string) error {
	v, err := strconv.ParseBool(s)
	*b = boolValue(v)
	return err
}

func (b *boolValue) Get() interface{} { return bool(*b) }

func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }

func (b *boolValue) IsBoolFlag() bool { return true }

이렇게 하려면 fs.actual[name]에서 Flag 형식의 값을 부여했습니다. 명령줄의 매개 변수 값 설정은 일단락되었고 다음에는 docker cli와 docker daemon의 상호작용을 계속 공유합니다.

좋은 웹페이지 즐겨찾기