am e0e56563: am 0bda352f: Merge changes from topic \'logcatd\'

* commit 'e0e565635a7c6c36a05282622c01203afbec5ca5':
  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:
Mark Salyzyn 2015-06-02 22:41:29 +00:00 committed by Android Git Automerger
commit 560515540d
10 changed files with 182 additions and 18 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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(&param, 0, sizeof(param));
if (sched_setscheduler((pid_t) 0, SCHED_BATCH, &param) < 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':

View File

@ -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))

View File

@ -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>

36
logd/logpersist Executable file
View File

@ -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

View File

@ -666,3 +666,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