am 56051554: am e0e56563: am 0bda352f: Merge changes from topic \'logcatd\'
* commit '560515540d3ef4da9dc58e3b7fcfeb6c067bb677': init.rc: logd: Add logpersistd (nee logcatd) init: change exec parsing to make SECLABEL optional logcat: -f run in background logcat: -f flag to continue
This commit is contained in:
commit
d8a99287a4
|
@ -380,7 +380,8 @@ void service_start(struct service *svc, const char *dynamic_args)
|
|||
|
||||
if ((svc->flags & SVC_EXEC) != 0) {
|
||||
INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
|
||||
svc->pid, svc->uid, svc->gid, svc->nr_supp_gids, svc->seclabel);
|
||||
svc->pid, svc->uid, svc->gid, svc->nr_supp_gids,
|
||||
svc->seclabel ? : "default");
|
||||
waiting_for_exec = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -664,6 +664,7 @@ int action_queue_empty()
|
|||
|
||||
service* make_exec_oneshot_service(int nargs, char** args) {
|
||||
// Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
|
||||
// SECLABEL can be a - to denote default
|
||||
int command_arg = 1;
|
||||
for (int i = 1; i < nargs; ++i) {
|
||||
if (strcmp(args[i], "--") == 0) {
|
||||
|
@ -689,7 +690,7 @@ service* make_exec_oneshot_service(int nargs, char** args) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (command_arg > 2) {
|
||||
if ((command_arg > 2) && strcmp(args[1], "-")) {
|
||||
svc->seclabel = args[1];
|
||||
}
|
||||
if (command_arg > 3) {
|
||||
|
|
|
@ -180,7 +180,7 @@ exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*
|
|||
Fork and execute command with the given arguments. The command starts
|
||||
after "--" so that an optional security context, user, and supplementary
|
||||
groups can be provided. No other commands will be run until this one
|
||||
finishes.
|
||||
finishes. <seclabel> can be a - to denote default.
|
||||
|
||||
export <name> <value>
|
||||
Set the environment variable <name> equal to <value> in the
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <log/log_read.h>
|
||||
|
||||
const char log_time::default_format[] = "%m-%d %H:%M:%S.%3q";
|
||||
const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
|
||||
const timespec log_time::EPOCH = { 0, 0 };
|
||||
|
||||
// Add %#q for fractional seconds to standard strptime function
|
||||
|
|
|
@ -5,7 +5,7 @@ include $(CLEAR_VARS)
|
|||
|
||||
LOCAL_SRC_FILES:= logcat.cpp event.logtags
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
|
||||
|
||||
LOCAL_MODULE := logcat
|
||||
|
||||
|
|
|
@ -1,29 +1,38 @@
|
|||
// Copyright 2006-2015 The Android Open Source Project
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <base/file.h>
|
||||
#include <base/strings.h>
|
||||
#include <cutils/sched_policy.h>
|
||||
#include <cutils/sockets.h>
|
||||
#include <log/event_tag_map.h>
|
||||
#include <log/log.h>
|
||||
#include <log/log_read.h>
|
||||
#include <log/logger.h>
|
||||
#include <log/logd.h>
|
||||
#include <log/logger.h>
|
||||
#include <log/logprint.h>
|
||||
#include <log/event_tag_map.h>
|
||||
|
||||
#define DEFAULT_MAX_ROTATED_LOGS 4
|
||||
|
||||
|
@ -202,7 +211,15 @@ static void setupOutput()
|
|||
g_outFD = STDOUT_FILENO;
|
||||
|
||||
} else {
|
||||
struct stat statbuf;
|
||||
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
|
||||
fprintf(stderr, "failed to set background scheduling policy\n");
|
||||
}
|
||||
|
||||
struct sched_param param;
|
||||
memset(¶m, 0, sizeof(param));
|
||||
if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) {
|
||||
fprintf(stderr, "failed to set to batch scheduler\n");
|
||||
}
|
||||
|
||||
g_outFD = openLogFile (g_outputFileName);
|
||||
|
||||
|
@ -210,6 +227,7 @@ static void setupOutput()
|
|||
logcat_panic(false, "couldn't open output file");
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
if (fstat(g_outFD, &statbuf) == -1) {
|
||||
close(g_outFD);
|
||||
logcat_panic(false, "couldn't get output file stat\n");
|
||||
|
@ -231,7 +249,7 @@ static void show_help(const char *cmd)
|
|||
fprintf(stderr, "options include:\n"
|
||||
" -s Set default filter to silent.\n"
|
||||
" Like specifying filterspec '*:S'\n"
|
||||
" -f <filename> Log to file. Default to stdout\n"
|
||||
" -f <filename> Log to file. Default is stdout\n"
|
||||
" -r <kbytes> Rotate log every kbytes. Requires -f\n"
|
||||
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
|
||||
" -v <format> Sets the log print format, where <format> is:\n\n"
|
||||
|
@ -352,6 +370,86 @@ static void logcat_panic(bool showHelp, const char *fmt, ...)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static const char g_defaultTimeFormat[] = "%m-%d %H:%M:%S.%q";
|
||||
|
||||
// Find last logged line in gestalt of all matching existing output files
|
||||
static log_time lastLogTime(char *outputFileName) {
|
||||
log_time retval(log_time::EPOCH);
|
||||
if (!outputFileName) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
log_time now(CLOCK_REALTIME);
|
||||
|
||||
std::string directory;
|
||||
char *file = strrchr(outputFileName, '/');
|
||||
if (!file) {
|
||||
directory = ".";
|
||||
file = outputFileName;
|
||||
} else {
|
||||
*file = '\0';
|
||||
directory = outputFileName;
|
||||
*file = '/';
|
||||
++file;
|
||||
}
|
||||
size_t len = strlen(file);
|
||||
log_time modulo(0, NS_PER_SEC);
|
||||
std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(directory.c_str()), closedir);
|
||||
struct dirent *dp;
|
||||
while ((dp = readdir(dir.get())) != NULL) {
|
||||
if ((dp->d_type != DT_REG)
|
||||
|| strncmp(dp->d_name, file, len)
|
||||
|| (dp->d_name[len]
|
||||
&& ((dp->d_name[len] != '.')
|
||||
|| !isdigit(dp->d_name[len+1])))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string file_name = directory;
|
||||
file_name += "/";
|
||||
file_name += dp->d_name;
|
||||
std::string file;
|
||||
if (!android::base::ReadFileToString(file_name, &file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (const auto& line : android::base::Split(file, "\n")) {
|
||||
log_time t(log_time::EPOCH);
|
||||
char *ep = t.strptime(line.c_str(), g_defaultTimeFormat);
|
||||
if (!ep || (*ep != ' ')) {
|
||||
continue;
|
||||
}
|
||||
// determine the time precision of the logs (eg: msec or usec)
|
||||
for (unsigned long mod = 1UL; mod < modulo.tv_nsec; mod *= 10) {
|
||||
if (t.tv_nsec % (mod * 10)) {
|
||||
modulo.tv_nsec = mod;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We filter any times later than current as we may not have the
|
||||
// year stored with each log entry. Also, since it is possible for
|
||||
// entries to be recorded out of order (very rare) we select the
|
||||
// maximum we find just in case.
|
||||
if ((t < now) && (t > retval)) {
|
||||
retval = t;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// We count on the basename file to be the definitive end, so stop here.
|
||||
if (!dp->d_name[len] && found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retval == log_time::EPOCH) {
|
||||
return retval;
|
||||
}
|
||||
// tail_time prints matching or higher, round up by the modulo to prevent
|
||||
// a replay of the last entry we have just checked.
|
||||
retval += modulo;
|
||||
return retval;
|
||||
}
|
||||
|
||||
} /* namespace android */
|
||||
|
||||
|
||||
|
@ -417,12 +515,11 @@ int main(int argc, char **argv)
|
|||
/* FALLTHRU */
|
||||
case 'T':
|
||||
if (strspn(optarg, "0123456789") != strlen(optarg)) {
|
||||
char *cp = tail_time.strptime(optarg,
|
||||
log_time::default_format);
|
||||
char *cp = tail_time.strptime(optarg, g_defaultTimeFormat);
|
||||
if (!cp) {
|
||||
logcat_panic(false,
|
||||
"-%c \"%s\" not in \"%s\" time format\n",
|
||||
ret, optarg, log_time::default_format);
|
||||
ret, optarg, g_defaultTimeFormat);
|
||||
}
|
||||
if (*cp) {
|
||||
char c = *cp;
|
||||
|
@ -545,9 +642,11 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
|
||||
case 'f':
|
||||
if ((tail_time == log_time::EPOCH) && (tail_lines != 0)) {
|
||||
tail_time = lastLogTime(optarg);
|
||||
}
|
||||
// redirect output to a file
|
||||
g_outputFileName = optarg;
|
||||
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
|
|
|
@ -41,4 +41,15 @@ LOCAL_CFLAGS := -Werror $(event_flag)
|
|||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := logpersist.start
|
||||
LOCAL_MODULE_TAGS := debug
|
||||
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
LOCAL_MODULE_PATH := $(bin_dir)
|
||||
LOCAL_SRC_FILES := logpersist
|
||||
ALL_TOOLS := logpersist.start logpersist.stop logpersist.cat
|
||||
LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(filter-out $(LOCAL_MODULE),$(ALL_TOOLS)),ln -sf $(LOCAL_MODULE) $(TARGET_OUT)/bin/$(t);)
|
||||
include $(BUILD_PREBUILT)
|
||||
|
||||
include $(call first-makefiles-under,$(LOCAL_PATH))
|
||||
|
|
|
@ -10,6 +10,8 @@ ro.config.low_ram bool false if true, logd.statistics & logd.klogd
|
|||
default false
|
||||
ro.build.type string if user, logd.statistics & logd.klogd
|
||||
default false
|
||||
persist.logd.logpersistd string Enable logpersist daemon, "logcatd"
|
||||
turns on logcat -f in logd context
|
||||
persist.logd.size number 256K default size of the buffer for all
|
||||
log ids at initial startup, at runtime
|
||||
use: logcat -b all -G <value>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#! /system/bin/sh
|
||||
# logpersist cat start and stop handlers
|
||||
data=/data/misc/logd
|
||||
property=persist.logd.logpersistd
|
||||
service=logcatd
|
||||
progname="${0##*/}"
|
||||
if [ X"${1}" = "-h" -o X"${1}" = X"--help" ]; then
|
||||
echo "${progname%.*}.cat - dump current ${service%d} logs"
|
||||
echo "${progname%.*}.start - start ${service} service"
|
||||
echo "${progname%.*}.stop [--clear] - stop ${service} service"
|
||||
exit 0
|
||||
fi
|
||||
case ${progname} in
|
||||
*.cat)
|
||||
su 1036 ls "${data}" |
|
||||
tr -d '\r' |
|
||||
sort -ru |
|
||||
sed "s#^#${data}/#" |
|
||||
su 1036 xargs cat
|
||||
;;
|
||||
*.start)
|
||||
su 0 setprop ${property} ${service}
|
||||
getprop ${property}
|
||||
sleep 1
|
||||
ps -t | grep "${data##*/}.*${service%d}"
|
||||
;;
|
||||
*.stop)
|
||||
su 0 stop ${service}
|
||||
su 0 setprop ${property} ""
|
||||
[ X"${1}" != X"-c" -a X"${1}" != X"--clear" ] ||
|
||||
( sleep 1 ; su 1036,9998 rm -rf "${data}" )
|
||||
;;
|
||||
*)
|
||||
echo "Unexpected command ${0##*/} ${@}" >&2
|
||||
exit 1
|
||||
esac
|
|
@ -667,3 +667,17 @@ service perfprofd /system/xbin/perfprofd
|
|||
class late_start
|
||||
user root
|
||||
oneshot
|
||||
|
||||
on property:persist.logd.logpersistd=logcatd
|
||||
# all exec/services are called with umask(077), so no gain beyond 0700
|
||||
mkdir /data/misc/logd 0700 logd log
|
||||
# logd for write to /data/misc/logd, log group for read from pstore (-L)
|
||||
exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
|
||||
start logcatd
|
||||
|
||||
service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
|
||||
class late_start
|
||||
disabled
|
||||
# logd for write to /data/misc/logd, log group for read from log daemon
|
||||
user logd
|
||||
group log
|
||||
|
|
Loading…
Reference in New Issue