nix doctor: add more logging output to checks
When running nix doctor on a healthy system, it just prints the store URI and nothing else. This makes it unclear whether the system is in a good state and what check(s) it actually ran, since some of the checks are optional depending on the store type. This commit updates nix doctor to print an colored log message for every check that it does, and explicitly state whether that check was a PASS or FAIL to make it clear to the user whether the system passed its checkup with the doctor. Fixes #3084
This commit is contained in:
parent
93b1ce1ac5
commit
c5bd564c69
|
@ -1,11 +1,17 @@
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "command.hh"
|
#include "command.hh"
|
||||||
|
#include "logging.hh"
|
||||||
#include "serve-protocol.hh"
|
#include "serve-protocol.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
#include "util.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
std::string formatProtocol(unsigned int proto)
|
std::string formatProtocol(unsigned int proto)
|
||||||
{
|
{
|
||||||
if (proto) {
|
if (proto) {
|
||||||
|
@ -16,6 +22,18 @@ std::string formatProtocol(unsigned int proto)
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkPass(const std::string & msg) {
|
||||||
|
logger->log(ANSI_GREEN "[PASS] " ANSI_NORMAL + msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkFail(const std::string & msg) {
|
||||||
|
logger->log(ANSI_RED "[FAIL] " ANSI_NORMAL + msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct CmdDoctor : StoreCommand
|
struct CmdDoctor : StoreCommand
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
@ -27,13 +45,12 @@ struct CmdDoctor : StoreCommand
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
{
|
{
|
||||||
return "check your system for potential problems";
|
return "check your system for potential problems and print a PASS or FAIL for each check.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
std::cout << "Store uri: " << store->getUri() << std::endl;
|
logger->log("Running checks against store uri: " + store->getUri());
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
auto type = getStoreType();
|
auto type = getStoreType();
|
||||||
|
|
||||||
|
@ -56,15 +73,14 @@ struct CmdDoctor : StoreCommand
|
||||||
dirs.insert(dirOf(canonPath(dir + "/nix-env", true)));
|
dirs.insert(dirOf(canonPath(dir + "/nix-env", true)));
|
||||||
|
|
||||||
if (dirs.size() != 1) {
|
if (dirs.size() != 1) {
|
||||||
std::cout << "Warning: multiple versions of nix found in PATH." << std::endl;
|
std::stringstream ss;
|
||||||
std::cout << std::endl;
|
ss << "Multiple versions of nix found in PATH:\n";
|
||||||
for (auto & dir : dirs)
|
for (auto & dir : dirs)
|
||||||
std::cout << " " << dir << std::endl;
|
ss << " " << dir << "\n";
|
||||||
std::cout << std::endl;
|
return checkFail(ss.str());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return checkPass("PATH contains only one nix version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkProfileRoots(ref<Store> store)
|
bool checkProfileRoots(ref<Store> store)
|
||||||
|
@ -87,17 +103,17 @@ struct CmdDoctor : StoreCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dirs.empty()) {
|
if (!dirs.empty()) {
|
||||||
std::cout << "Warning: found profiles outside of " << settings.nixStateDir << "/profiles." << std::endl;
|
std::stringstream ss;
|
||||||
std::cout << "The generation this profile points to might not have a gcroot and could be" << std::endl;
|
ss << "Found profiles outside of " << settings.nixStateDir << "/profiles.\n"
|
||||||
std::cout << "garbage collected, resulting in broken symlinks." << std::endl;
|
<< "The generation this profile points to might not have a gcroot and could be\n"
|
||||||
std::cout << std::endl;
|
<< "garbage collected, resulting in broken symlinks.\n\n";
|
||||||
for (auto & dir : dirs)
|
for (auto & dir : dirs)
|
||||||
std::cout << " " << dir << std::endl;
|
ss << " " << dir << "\n";
|
||||||
std::cout << std::endl;
|
ss << "\n";
|
||||||
return false;
|
return checkFail(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return checkPass("All profiles are gcroots.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkStoreProtocol(unsigned int storeProto)
|
bool checkStoreProtocol(unsigned int storeProto)
|
||||||
|
@ -107,17 +123,16 @@ struct CmdDoctor : StoreCommand
|
||||||
: PROTOCOL_VERSION;
|
: PROTOCOL_VERSION;
|
||||||
|
|
||||||
if (clientProto != storeProto) {
|
if (clientProto != storeProto) {
|
||||||
std::cout << "Warning: protocol version of this client does not match the store." << std::endl;
|
std::stringstream ss;
|
||||||
std::cout << "While this is not necessarily a problem it's recommended to keep the client in" << std::endl;
|
ss << "Warning: protocol version of this client does not match the store.\n"
|
||||||
std::cout << "sync with the daemon." << std::endl;
|
<< "While this is not necessarily a problem it's recommended to keep the client in\n"
|
||||||
std::cout << std::endl;
|
<< "sync with the daemon.\n\n"
|
||||||
std::cout << "Client protocol: " << formatProtocol(clientProto) << std::endl;
|
<< "Client protocol: " << formatProtocol(clientProto) << "\n"
|
||||||
std::cout << "Store protocol: " << formatProtocol(storeProto) << std::endl;
|
<< "Store protocol: " << formatProtocol(storeProto) << "\n\n";
|
||||||
std::cout << std::endl;
|
return checkFail(ss.str());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return checkPass("Client protocol matches store protocol.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue