mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-30 18:36:22 +01:00 
			
		
		
		
	Add a new command doctor to check if some wrong configurations on gitea instance (#9095)
* add doctor * Add a new command doctor to check if some wrong configurations on gitea instance * fix import * use regex match authorized_keys on doctor * Add documentation
This commit is contained in:
		
				
					committed by
					
						 Antoine GIRARD
						Antoine GIRARD
					
				
			
			
				
	
			
			
			
						parent
						
							f2e6c4538e
						
					
				
				
					commit
					f69f5a9f10
				
			
							
								
								
									
										130
									
								
								cmd/doctor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								cmd/doctor.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| // Copyright 2019 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
|  | ||||
| 	"github.com/urfave/cli" | ||||
| ) | ||||
|  | ||||
| // CmdDoctor represents the available doctor sub-command. | ||||
| var CmdDoctor = cli.Command{ | ||||
| 	Name:        "doctor", | ||||
| 	Usage:       "Diagnose the problems", | ||||
| 	Description: "A command to diagnose the problems of current gitea instance according the given configuration.", | ||||
| 	Action:      runDoctor, | ||||
| } | ||||
|  | ||||
| type check struct { | ||||
| 	title string | ||||
| 	f     func(ctx *cli.Context) ([]string, error) | ||||
| } | ||||
|  | ||||
| // checklist represents list for all checks | ||||
| var checklist = []check{ | ||||
| 	{ | ||||
| 		title: "Check if OpenSSH authorized_keys file id correct", | ||||
| 		f:     runDoctorLocationMoved, | ||||
| 	}, | ||||
| 	// more checks please append here | ||||
| } | ||||
|  | ||||
| func runDoctor(ctx *cli.Context) error { | ||||
| 	err := initDB() | ||||
| 	fmt.Println("Using app.ini at", setting.CustomConf) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		fmt.Println("Check if you are using the right config file. You can use a --config directive to specify one.") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	for i, check := range checklist { | ||||
| 		fmt.Println("[", i+1, "]", check.title) | ||||
| 		if messages, err := check.f(ctx); err != nil { | ||||
| 			fmt.Println("Error:", err) | ||||
| 		} else if len(messages) > 0 { | ||||
| 			for _, message := range messages { | ||||
| 				fmt.Println("-", message) | ||||
| 			} | ||||
| 		} else { | ||||
| 			fmt.Println("OK.") | ||||
| 		} | ||||
| 		fmt.Println() | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func exePath() (string, error) { | ||||
| 	file, err := exec.LookPath(os.Args[0]) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return filepath.Abs(file) | ||||
| } | ||||
|  | ||||
| func runDoctorLocationMoved(ctx *cli.Context) ([]string, error) { | ||||
| 	if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys") | ||||
| 	f, err := os.Open(fPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| 	var firstline string | ||||
| 	scanner := bufio.NewScanner(f) | ||||
| 	for scanner.Scan() { | ||||
| 		firstline = strings.TrimSpace(scanner.Text()) | ||||
| 		if len(firstline) == 0 || firstline[0] == '#' { | ||||
| 			continue | ||||
| 		} | ||||
| 		break | ||||
| 	} | ||||
|  | ||||
| 	// command="/Volumes/data/Projects/gitea/gitea/gitea --config | ||||
| 	if len(firstline) > 0 { | ||||
| 		exp := regexp.MustCompile(`^[ \t]*(?:command=")([^ ]+) --config='([^']+)' serv key-([^"]+)",(?:[^ ]+) ssh-rsa ([^ ]+) ([^ ]+)[ \t]*$`) | ||||
|  | ||||
| 		// command="/home/user/gitea --config='/home/user/etc/app.ini' serv key-999",option-1,option-2,option-n ssh-rsa public-key-value key-name | ||||
| 		res := exp.FindStringSubmatch(firstline) | ||||
| 		if res == nil { | ||||
| 			return nil, errors.New("Unknow authorized_keys format") | ||||
| 		} | ||||
|  | ||||
| 		giteaPath := res[1] // => /home/user/gitea | ||||
| 		iniPath := res[2]   // => /home/user/etc/app.ini | ||||
|  | ||||
| 		p, err := exePath() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		p, err = filepath.Abs(p) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		if len(giteaPath) > 0 && giteaPath != p { | ||||
| 			return []string{fmt.Sprintf("Gitea exe path wants %s but %s on %s", p, giteaPath, fPath)}, nil | ||||
| 		} | ||||
| 		if len(iniPath) > 0 && iniPath != setting.CustomConf { | ||||
| 			return []string{fmt.Sprintf("Gitea config path wants %s but %s on %s", setting.CustomConf, iniPath, fPath)}, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil, nil | ||||
| } | ||||
| @@ -289,3 +289,28 @@ This command is idempotent. | ||||
|  | ||||
| #### convert | ||||
| Converts an existing MySQL database from utf8 to utf8mb4. | ||||
|  | ||||
| #### doctor | ||||
| Diagnose the problems of current gitea instance according the given configuration. | ||||
| Currently there are a check list below: | ||||
|  | ||||
| - Check if OpenSSH authorized_keys file id correct | ||||
| When your gitea instance support OpenSSH, your gitea instance binary path will be written to `authorized_keys`  | ||||
| when there is any public key added or changed on your gitea instance. | ||||
| Sometimes if you moved or renamed your gitea binary when upgrade and you haven't run `Update the '.ssh/authorized_keys' file with Gitea SSH keys. (Not needed for the built-in SSH server.)` on your Admin Panel. Then all pull/push via SSH will not be work. | ||||
| This check will help you to check if it works well. | ||||
|  | ||||
| For contributors, if you want to add more checks, you can wrie ad new function like `func(ctx *cli.Context) ([]string, error)` and  | ||||
| append it to `doctor.go`. | ||||
|  | ||||
| ```go | ||||
| var checklist = []check{ | ||||
| 	{ | ||||
| 		title: "Check if OpenSSH authorized_keys file id correct", | ||||
| 		f:     runDoctorLocationMoved, | ||||
|     }, | ||||
|     // more checks please append here | ||||
| } | ||||
| ``` | ||||
|  | ||||
| This function will receive a command line context and return a list of details about the problems or error. | ||||
		Reference in New Issue
	
	Block a user