@@ -617,20 +617,41 @@ namespace vix::commands
617617 return std::system (cmd.c_str ()) == 0 ;
618618 }
619619
620- std::optional <std::string> detect_systemd_service ( const std::string &projectName )
620+ std::vector <std::string> list_systemd_services ( )
621621 {
622- const std::string lower = lower_copy (projectName) ;
622+ std::vector<std:: string> services ;
623623
624624 auto out = run_capture (
625- " systemctl list-units --type=service --all --no-legend 2>/dev/null | "
626- " awk '{print $1}' | grep -i " +
627- shell_quote (lower) +
628- " | head -1" );
625+ " systemctl list-unit-files --type=service --no-legend 2>/dev/null | "
626+ " awk '{print $1}'" );
627+
628+ if (!out)
629+ return services;
630+
631+ std::string current;
632+
633+ for (char c : *out)
634+ {
635+ if (c == ' \n ' || c == ' \r ' )
636+ {
637+ current = trim_copy (current);
638+
639+ if (!current.empty ())
640+ services.push_back (current);
641+
642+ current.clear ();
643+ continue ;
644+ }
645+
646+ current.push_back (c);
647+ }
629648
630- if (out && !trim_copy (*out).empty ())
631- return trim_copy (*out);
649+ current = trim_copy (current);
632650
633- return lower + " .service" ;
651+ if (!current.empty ())
652+ services.push_back (current);
653+
654+ return services;
634655 }
635656
636657 std::optional<std::string> systemctl_property (
@@ -655,6 +676,54 @@ namespace vix::commands
655676 return value;
656677 }
657678
679+ bool service_points_to_project (
680+ const std::string &service,
681+ const fs::path &projectDir,
682+ const std::optional<fs::path> &binary)
683+ {
684+ const auto workingDir = systemctl_property (service, " WorkingDirectory" );
685+ const auto execStart = systemctl_property (service, " ExecStart" );
686+
687+ std::error_code ec;
688+ const fs::path canonicalProject =
689+ fs::weakly_canonical (projectDir, ec);
690+
691+ if (workingDir && !workingDir->empty ())
692+ {
693+ std::error_code wdEc;
694+ const fs::path canonicalWorkingDir =
695+ fs::weakly_canonical (fs::path (*workingDir), wdEc);
696+
697+ if (!wdEc && !ec && canonicalWorkingDir == canonicalProject)
698+ return true ;
699+
700+ if (trim_copy (*workingDir) == projectDir.string ())
701+ return true ;
702+ }
703+
704+ if (binary && execStart && !execStart->empty ())
705+ {
706+ const std::string exec = *execStart;
707+ const std::string bin = binary->string ();
708+
709+ if (!bin.empty () && exec.find (bin) != std::string::npos)
710+ return true ;
711+
712+ if (binary->has_filename ())
713+ {
714+ const std::string filename = binary->filename ().string ();
715+
716+ if (!filename.empty () && exec.find (filename) != std::string::npos)
717+ {
718+ if (workingDir && trim_copy (*workingDir) == projectDir.string ())
719+ return true ;
720+ }
721+ }
722+ }
723+
724+ return false ;
725+ }
726+
658727 bool systemd_service_exists (const std::string &service)
659728 {
660729 const std::string cmd =
@@ -663,6 +732,31 @@ namespace vix::commands
663732 return std::system (cmd.c_str ()) == 0 ;
664733 }
665734
735+ std::optional<std::string> detect_systemd_service (
736+ const std::string &projectName,
737+ const fs::path &projectDir,
738+ const std::optional<fs::path> &binary)
739+ {
740+ const std::string lower = lower_copy (projectName);
741+ const std::string exactService = lower + " .service" ;
742+
743+ if (systemd_service_exists (exactService) &&
744+ service_points_to_project (exactService, projectDir, binary))
745+ {
746+ return exactService;
747+ }
748+
749+ const auto services = list_systemd_services ();
750+
751+ for (const auto &service : services)
752+ {
753+ if (service_points_to_project (service, projectDir, binary))
754+ return service;
755+ }
756+
757+ return std::nullopt ;
758+ }
759+
666760 std::optional<std::string> detect_listening_port_for_binary (const fs::path &binary)
667761 {
668762 if (binary.empty () || !have_cmd (" ss" ))
@@ -781,8 +875,12 @@ namespace vix::commands
781875 const auto buildDir = detect_build_dir ();
782876 const auto binary = detect_binary_path (projectName);
783877
784- const auto service = detect_systemd_service (projectName);
785- const bool serviceExists = service && systemd_service_exists (*service);
878+ const auto service = detect_systemd_service (
879+ projectName,
880+ fs::current_path (),
881+ binary);
882+
883+ const bool serviceExists = service.has_value ();
786884
787885 const auto serviceStatus =
788886 serviceExists ? systemctl_property (*service, " ActiveState" ) : std::nullopt ;
0 commit comments