@@ -36,6 +36,25 @@ func NewTaskExecutor() *TaskExecutor {
3636 }
3737}
3838
39+ func resolveBinaryPath (name string ) string {
40+ for _ , candidate := range []string {
41+ name ,
42+ filepath .Join ("/opt/dbops-pxc/usr/sbin" , name ),
43+ filepath .Join ("/opt/dbops-pxc/usr/bin" , name ),
44+ filepath .Join ("/usr/sbin" , name ),
45+ filepath .Join ("/usr/bin" , name ),
46+ filepath .Join ("/usr/local/mysql/bin" , name ),
47+ } {
48+ if p , err := exec .LookPath (candidate ); err == nil {
49+ return p
50+ }
51+ if st , err := os .Stat (candidate ); err == nil && ! st .IsDir () {
52+ return candidate
53+ }
54+ }
55+ return name
56+ }
57+
3958func (e * TaskExecutor ) SetRelayConfig (relayHost string , relayPort int , relayToken string ) {
4059 if relayHost != "" {
4160 e .relayCli = newRelayClient (relayHost , relayPort , relayToken )
@@ -617,7 +636,7 @@ func (e *TaskExecutor) deploySingleInstance(ctx context.Context, req DeployTaskR
617636 }
618637 } else {
619638 // Legacy: rely on PATH
620- mysqld = "mysqld"
639+ mysqld = resolveBinaryPath ( "mysqld" )
621640 if basedir != "" {
622641 mysqld = filepath .Join (basedir , "bin" , "mysqld" )
623642 }
@@ -728,7 +747,7 @@ func (e *TaskExecutor) deploySingleInstance(ctx context.Context, req DeployTaskR
728747 // Skip the original password setup - it seems to return success but doesn't actually set the password
729748 // We'll handle it in the health check retry logic below
730749
731- healthCmd := exec .CommandContext (ctx , "mysqladmin" , "-h" , host , "-P" , fmt .Sprintf ("%d" , port ), "-u" , defaultString (mysqlUser , "root" ), "ping" )
750+ healthCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysqladmin" ) , "-h" , host , "-P" , fmt .Sprintf ("%d" , port ), "-u" , defaultString (mysqlUser , "root" ), "ping" )
732751 if mysqlPass != "" {
733752 healthCmd .Env = append (os .Environ (), "MYSQL_PWD=" + mysqlPass )
734753 }
@@ -748,14 +767,14 @@ func (e *TaskExecutor) deploySingleInstance(ctx context.Context, req DeployTaskR
748767 escapeSQL (mysqlUser ), escapeSQL (mysqlPass ),
749768 escapeSQL (mysqlUser ),
750769 )
751- retryCmd := exec .CommandContext (ctx , "mysql" , "-S" , socketPath , "-u" , mysqlUser , "-e" , retrySQL )
770+ retryCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , "-S" , socketPath , "-u" , mysqlUser , "-e" , retrySQL )
752771 retryOut , retryErr := retryCmd .CombinedOutput ()
753772 if retryErr != nil {
754773 fmt .Fprintf (os .Stderr , "Password setup via socket failed: %v, output: %s\n " , retryErr , string (retryOut ))
755774 }
756775
757776 // Try health check again after password setup
758- retryHealthCmd := exec .CommandContext (ctx , "mysqladmin" , "-h" , host , "-P" , fmt .Sprintf ("%d" , port ), "-u" , mysqlUser , "ping" )
777+ retryHealthCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysqladmin" ) , "-h" , host , "-P" , fmt .Sprintf ("%d" , port ), "-u" , mysqlUser , "ping" )
759778 retryHealthCmd .Env = append (os .Environ (), "MYSQL_PWD=" + mysqlPass )
760779 if retryHealthCmd .Run () == nil {
761780 // Success! Now initialize MGR if needed
@@ -837,7 +856,7 @@ func initializeMGR(ctx context.Context, host string, port int, user, pass string
837856 SET GLOBAL super_read_only=0;
838857 SET GLOBAL read_only=0;
839858 `
840- disableCmd := exec .CommandContext (ctx , "mysql" , append (baseCmd , "-e" , disableReadOnlySQL )... )
859+ disableCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , append (baseCmd , "-e" , disableReadOnlySQL )... )
841860 disableCmd .Env = env
842861 if out , err := disableCmd .CombinedOutput (); err != nil {
843862 return fmt .Errorf ("disable read-only failed: %v, output: %s" , err , string (out ))
@@ -853,7 +872,7 @@ func initializeMGR(ctx context.Context, host string, port int, user, pass string
853872 CHANGE REPLICATION SOURCE TO SOURCE_USER='repl', SOURCE_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';
854873 `
855874
856- replCmd := exec .CommandContext (ctx , "mysql" , append (baseCmd , "-e" , replicationSQL )... )
875+ replCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , append (baseCmd , "-e" , replicationSQL )... )
857876 replCmd .Env = env
858877 if out , err := replCmd .CombinedOutput (); err != nil {
859878 return fmt .Errorf ("create replication user failed: %v, output: %s" , err , string (out ))
@@ -867,15 +886,15 @@ func initializeMGR(ctx context.Context, host string, port int, user, pass string
867886 START GROUP_REPLICATION;
868887 SET GLOBAL group_replication_bootstrap_group=OFF;
869888 `
870- bootCmd := exec .CommandContext (ctx , "mysql" , append (baseCmd , "-e" , bootstrapSQL )... )
889+ bootCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , append (baseCmd , "-e" , bootstrapSQL )... )
871890 bootCmd .Env = env
872891 if out , err := bootCmd .CombinedOutput (); err != nil {
873892 return fmt .Errorf ("bootstrap MGR failed: %v, output: %s" , err , string (out ))
874893 }
875894 } else {
876895 // 副本节点:直接start
877896 startSQL := "START GROUP_REPLICATION;"
878- startCmd := exec .CommandContext (ctx , "mysql" , append (baseCmd , "-e" , startSQL )... )
897+ startCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , append (baseCmd , "-e" , startSQL )... )
879898 startCmd .Env = env
880899 if out , err := startCmd .CombinedOutput (); err != nil {
881900 return fmt .Errorf ("start MGR failed: %v, output: %s" , err , string (out ))
@@ -887,7 +906,7 @@ func initializeMGR(ctx context.Context, host string, port int, user, pass string
887906
888907 // 4. 验证MGR状态
889908 checkSQL := "SELECT MEMBER_STATE FROM performance_schema.replication_group_members WHERE MEMBER_ID=@@server_uuid;"
890- checkCmd := exec .CommandContext (ctx , "mysql" , append (baseCmd , "-N" , "-e" , checkSQL )... )
909+ checkCmd := exec .CommandContext (ctx , resolveBinaryPath ( "mysql" ) , append (baseCmd , "-N" , "-e" , checkSQL )... )
891910 checkCmd .Env = env
892911 out , err := checkCmd .CombinedOutput ()
893912 if err != nil {
0 commit comments