Читать один модуль npm в день (1) — имя пользователя

Node.js Linux Командная строка NPM

В последнее время я занят работой, и у меня с каждым днем ​​остается все меньше времени на получение знаний, я глубоко чувствую, что это не способствует моему техническому совершенствованию. просто помнидядя волкСказал: «Лучший способ изучить Node.js, когда вы потерялись —Смотрите десять модулей npm в день«Хотя у меня не так много времени, чтобы читать десять модулей в день, время как губка, и все же можно читать один модуль в день, когда его сжимаешь.

Я надеюсь, что с помощью этой серии статей, с одной стороны, я напомню себе о необходимости помнить об изначальном замысле технологии в своей работе, а с другой стороны, я буду поощрять себя продолжать двигаться вперед по пути Node. .js.

вступление в одно предложение

Первый модуль npm, который я выбираю, этоusername, используется для получения имени пользователя текущего пользователя, текущая версия — 3.0.0, а еженедельный объем загрузки — более 60 000.

использование

usernameПоддерживает синхронную и асинхронную запись Promise:

const username = require('username');
 
// 同步
console.log(username.sync()); // => 'elvin'

// 异步
username().then(username => {
    console.log(username); // => 'elvin'
});

Изучение исходного кода

Здесь более 20 строк основного кода, и основная логика такова:

  1. сначала черезprocess.envЗначение в переменной получает имя пользователя, если оно существует, возвращает его напрямую;
  2. Тогда, если естьos.userinfoфункцию, черезos.userinfo().usernameполучить имя пользователя и вернуться;
  3. Если все вышеперечисленные методы не помогли, под OS X/Linux, выполнивid -unкоманда, через WindowswhoamiКоманда получает имя пользователя и возвращает.

Далее мы рассмотрим эти три шага в сочетании с исходным кодом.

process.env

// 源代码 1-1
function getEnvVar() {
  const env = process.env;

  return env.SUDO_USER ||
    env.C9_USER /* Cloud9 */ ||
    env.LOGNAME ||
    env.USER ||
    env.LNAME ||
    env.USERNAME;
}

const envVar = getEnvVar();

if (envVar) {
  return Promise.resolve(envVar);
}

process.envВозвращает объект, содержащий текущие переменные среды пользователя, которые можно выполнить в командной строке.printenvкоманда для просмотра всех переменных среды, вы также можетеprintenv v_nameКоманда для получения значения переменной окружения:

$ printenv
// => LANG=zh_CN.UTF-8
// => PWD=/Users/elvin/
// => SHELL=/bin/zsh
// => USER=elvin
// => ...

$ printenv USER
// => elvin

Переменные оболочки легко спутать с переменными окружения.setКоманда для просмотра всех переменных оболочки. Чтобы узнать о разнице между ними и предложениях по использованию, обратитесь к этому материалу на английском языке.How To Read and Set Environmental and Shell Variables on a Linux VPS.

В Node.js оprocess.envЕсть еще три места, которые нужно знать:

  1. в состоянии пройтиprocess.env.foo = "bar"Способ установки переменных среды, в настоящее время разрешены все типы значений и они будут преобразованы в строковый тип, согласноофициальная документация, в будущих версиях будут разрешены только значения типа string, number и boolean, установка значений других типов вызовет исключение.

    process.env.foo = undefined;
    console.log(process.env.foo, typeof process.env.foo);
    // => 'undefined', 'string'
    
    process.env.foo = {};
    console.log(process.env.foo, typeof process.env.foo);
    // => '[object Object]', 'string'
    
  2. в состоянии пройтиdeleteспособ удаления переменных окружения.

    process.env.foo = undefined;
    delete process.env.foo
    console.log(process.env.foo)
    // => undefined
    
  3. в Node.jsprocess.envМодификации не будут отражаться за пределами процесса ноды, но переменные окружения можно задавать извне, а затем получать через код Node.js, который на практике часто задается таким образомNODE_ENVпеременная, а затем прочитайте ее значение в коде конфигурации веб-пакета, чтобы определить среду для разных сборок.

    $ node -e 'process.env.foo = "bar"' && echo $foo
    // => 空
    
    $ NODE_ENV=production node -e 'console.log(process.env.NODE_ENV)'
    // => 'production'
    

    Напрямую не поддерживается под WindowsNODE_ENV=productionТаким образом, вам нужно установитьcross-envпакет для совместимости.

вернуться к исходному коду 1-1getEnvVarфункции, вы можете видеть, что последовательные попытки выполняются изprocess.envПеременные среды SUDO_USER, C9_USER, LOGNAME, USER, LNAME и USERNAME получают имя пользователя, которое здесь выделено.SUDO_USERиC9_USERЭти две переменные:

  1. Если идентификатор пользователя root,USERпеременная возвращает корень, аSUDO_USERПеременная возвращает имя учетной записи, вошедшей в систему как root, например: когда я вхожу в систему как учетная запись elvinsudo suСтав пользователем root,USERвернет корень,SUDO_USERвернется эльф.

    $ sudo su
    // => input password
    
    $ printenv USER
    // => root
    
    $ printenv SUDO_USER
    // => elvin
    
  2. C9_USERСудя по комментариям, это дляCloud9Это облачная среда разработки, запущенная Amazon для написания, запуска и отладки кода. Заинтересованные студенты могут попробовать ее.

os.userInfo

исходный код изprocess.envКогда имя пользователя не может быть получено, оно попытается передатьos.userInfo()Функция для получения:

// 源代码 1-2
if (os.userInfo) {
    return Promise.resolve(os.userInfo().username);
}

os.userinfo()Возвращается некоторая информация о текущем пользователе по сравнению сprocess.envС точки зрения информации информации намного меньше, и поддерживается только Node.js V6.0 и выше:

const os = require('os');

console.log(os.userInfo());

// => {
// => 	uid: 501,
// => 	gid: 20,
// => 	username: 'elvin',
// => 	homedir: '/Users/elvin',
// => 	shell: '/bin/zsh'
// => }

Вышеуказанные поля означают:

  • uid: идентификатор пользователя (user id), каждый пользователь идентифицируется уникальным идентификатором в системе, например id 501 означает пользователя elvin. В системах Linux информация об uid хранится в/etc/passwdВ файле uid пользователя root равен 0.
  • gid: идентификатор группы (идентификатор группы), к которой принадлежит пользователь. Пользователь может принадлежать к нескольким группам. Например, gid 20 означает, что пользователь elvin принадлежит к группе с идентификатором 20. В системах OS X/Linux информация gid хранится в/etc/groupВ файле gid пользователя root равен 0.
  • имя пользователя: Текущее имя пользователя, при входе в систему под пользователем elvin оно возвращает root вместо elvin.
  • homedir: домашний каталог текущего пользователя.
  • shell: путь к оболочке текущего пользователя.

выполнить команду командной строки

Если имя пользователя не может быть получено двумя текущими методами, оно будет передано под OS X/Linux.id -unКоманда для получения имени пользователя, под Windows оно будет переданоwhoamiКоманда для получения имени пользователя.

// 源代码 1-3
function cleanWinCmd(x) {
	return x.replace(/^.*\\/, '');
}

function noop() {}

if (process.platform === 'darwin' || process.platform === 'linux') {
    return execa('id', ['-un']).then(x => x.stdout).catch(noop);
} else if (process.platform === 'win32') {
    return execa('whoami').then(x => cleanWinCmd(x.stdout)).catch(noop);
}

Приведенный выше код сначала проходитprocess.platformОпределите операционную систему, если это OS X (т.е. darwin) или Linux, выполнитеid -unПолучите имя пользователя; если это Windows (например, win32), выполнитеwhoamiПолучите платформу и имя пользователя, затем пройдитеcleanWinCmdФункция использует регулярные выражения для извлечения имен пользователей. Фактически, его также можно передать на OS X/Linux.whoamiПолучите имя пользователя, но в документации оно объявлено какidКоманда устарела.

в соответствии сДокументация Node.js,process.platformОн вернет текущую платформу, в том числе aix | darwin | freebsd | linux | openbsd | sunos | win32 | android, поэтому на самом деле видно, что приведенный выше код рассматривает только три случая, и я лично думаю, что некоторые модификации могут быть сделано следующим образом:

if (process.platform === 'win32') {
    return execa('whoami').then(x => cleanWinCmd(x.stdout)).catch(noop);
} else {
    return execa('id', ['-un']).then(x => x.stdout).catch(noop);
}

Предложенные здесь улучшения принятыPR #20Слился с последним кодом 😊

В исходном коде 1-3,noopТакже стоит изучить использование пустых функций: когда выполнение команды ненормально, передатьnoopФункция проглатывает ошибку и возвращаетundefined. Сначала мне было бы любопытно, почему подробная информация об исключении не возвращается, чтобы облегчить поиск при возникновении ошибки, но затем, с точки зрения пользователя пакета, я думаю, что она возвращается напрямую.undefinedЕсть два преимущества:

  1. Как пользователь, вы, как правило, заботитесь только о том, сможете ли вы получить правильный результат, и не заботитесь о ненормальной информации внутри пакета.В настоящее время подробная информация об ошибке является своего рода помехой.
  2. возвращениеundefinedЕсли это так, пользователю будет проще писать код вызова, конечно, это связано с личным стилем.

Кроме того, следует отметить, что здесь используются сторонние пакеты.execaвместо встроенного Node.jschild_process.execмодуль для выполнения команд командной строки,execaОн был улучшен на основе нативного модуля, и текущий еженедельный объем загрузки составляет около 6 млн. Здесь он в основном использует свой интерфейс для предоставления Promise.

напиши в конце

пройти сегодняusernameШестьдесят строк кода:

  1. Понимание переменных системной среды, пониманиеSUDO_USERиUSERразница между переменными;
  2. Изучите Node.jsprocess.envдобавления, удаления и исправления;
  3. Узнайте о Node.jsos.userInfo()информация возвращена;
  4. знаниеprocess.platformВозвращает больше, чем darwin | win32 | Linux, может бытьusernameЗдесь может быть лучшая управляемость;
  5. noopПреимущество пустых функций в том, что они проглатывают исключения, когда промисы терпят неудачу.

фактическиusernameтакже прошлоmemПакет буферизует результаты для повышения эффективности, прочитаю завтраmemпакет для обучения.

О себе: Окончил Хуаке, работаю в Tencent,блог ЭлвинаДобро пожаловать в гости ^_^