ব্যবহারকারীর নাম কোনও আইডির সাথে যুক্ত হওয়ার জন্য পসিক্স সুসংগত উপায়


23

আমি প্রায়শই কোনও ব্যবহারকারীর আইডির সাথে যুক্ত লগইন নামটি পেতে চাই এবং এটি সাধারণ ব্যবহারের ক্ষেত্রে প্রমাণিত হওয়ায় আমি এটি করার জন্য একটি শেল ফাংশন লেখার সিদ্ধান্ত নিয়েছি। আমি প্রাথমিকভাবে জিএনইউ / লিনাক্স বিতরণগুলি ব্যবহার করার সময়, আমার স্ক্রিপ্টগুলি যথাসম্ভব পোর্টেবল হওয়ার জন্য এবং আমি যা করছি তা পসিক্স-সামঞ্জস্যপূর্ণ কিনা তা পরীক্ষা করার চেষ্টা করি।

ব্যকরণগত /etc/passwd

আমি যে প্রথম পদ্ধতির চেষ্টা করেছি তা হ'ল পার্স /etc/passwd(ব্যবহার awk)।

awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd

যাইহোক, এই পদ্ধতির সাথে সমস্যাটি হ'ল লগইনগুলি স্থানীয় নাও হতে পারে, উদাহরণস্বরূপ, ব্যবহারকারীর প্রমাণীকরণ NIS বা LDAP এর মাধ্যমে হতে পারে।

getentকমান্ডটি ব্যবহার করুন

ব্যবহার getent passwdকরা পার্সিংয়ের চেয়ে বেশি পোর্টেবল /etc/passwdকারণ এটি অ-স্থানীয় এনআইএস বা এলডিএপি ডাটাবেসকেও অনুসন্ধান করে।

getent passwd "$uid" | cut -d: -f1

দুর্ভাগ্যক্রমে, getentইউটিলিটিটি পসিক্স দ্বারা নির্দিষ্ট করা মনে হচ্ছে না।

idকমান্ডটি ব্যবহার করুন

id ব্যবহারকারীর পরিচয় সম্পর্কে ডেটা পাওয়ার জন্য পসিক্স-মানকৃত ইউটিলিটি।

BSD এবং GNU বাস্তবায়নগুলি একটি ব্যবহারকারী আইডি অপারেন্ড হিসাবে গ্রহণ করে:

এর অর্থ এটি কোনও ব্যবহারকারীর আইডির সাথে যুক্ত লগইন নামটি মুদ্রণের জন্য ব্যবহার করা যেতে পারে:

id -nu "$uid"

তবে অপারেন্ড হিসাবে ব্যবহারকারী আইডি সরবরাহ করা পসিক্সে নির্দিষ্ট করা হয়নি; এটি কেবল অপারেন্ড হিসাবে লগইন নামের ব্যবহারের বর্ণনা দেয় ।

উপরোক্ত সমস্ত সংমিশ্রণ

আমি উপরোক্ত তিনটি পদ্ধতির সমন্বয়ের বিষয়টি নিম্নলিখিতগুলির মতো কিছুতে বিবেচনা করেছি:

get_username(){
    uid="$1"
    # First try using getent
    getent passwd "$uid" | cut -d: -f1 ||
        # Next try using the UID as an operand to id.
        id -nu "$uid" ||
        # As a last resort, parse `/etc/passwd`.
        awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}

যাইহোক, এটি আটকানো, অচল এবং আরও গুরুত্বপূর্ণ - মজবুত নয়; এটি ব্যবহারকারীর আইডি অবৈধ বা বিদ্যমান না থাকলে এটি শূন্য-শর্তহীন অবস্থার সাথে প্রস্থান করে। আমি লম্বা এবং ক্লানকিয়ার শেল স্ক্রিপ্ট লিখার আগে যা প্রতিটি কমান্ডের অনুরোধের প্রস্থান স্থিতি বিশ্লেষণ করে এবং সঞ্চয় করে রাখে, আমি ভেবেছিলাম আমি এখানে জিজ্ঞাসা করব:

লগ-ইন নামটি কোনও ব্যবহারকারীর আইডির সাথে যুক্ত করার জন্য আরও কি মার্জিত এবং বহনযোগ্য (পসিক্স-সামঞ্জস্যপূর্ণ) উপায় আছে?


10
অতিরিক্ত মজাদার জন্য বিবেচনা করুন যে একাধিক ব্যবহারকারীর নাম একই
আইডিতে

এই প্রশ্নের প্রসঙ্গে একই আইডিতে একাধিক ব্যবহারকারীর নাম ম্যাপ করা সমস্যাটি হ'ল প্রথম ম্যাচের আগে কোনও কিছুই ফেরত দেবে না getentবা idকরবে না ; তাদের সমস্ত সন্ধান করার একমাত্র উপায় হ'ল সমস্ত ব্যবহারকারীকে গণনা করা, যদি ব্যবহারকারী ডাটাবেস এটির অনুমতি দেয়। ( /etc/passwdসেখানে সংজ্ঞায়িত ব্যবহারকারীদের জন্য কাজগুলি সন্ধান করছেন , স্পষ্টতই।)
স্টিফেন কিট

1
ধন্যবাদ @StephenKitt আমি আমার এ ধরনের একটি এন্ট্রি নির্মিত /etc/passwdএবং /etc/shadowএই দৃশ্যকল্প পরীক্ষা এবং যাচাই উভয় যে idএবং getent passwdআচরণ দেখে আপনি বর্ণনা। যদি, কোনও পর্যায়ে, আমি এমন একটি সিস্টেম ব্যবহার করে শেষ করি যেখানে ব্যবহারকারীর একাধিক নাম থাকে, আমি এই সিস্টেম ইউটিলিটিগুলির মতোই করব এবং কেবল প্রথম ব্যবহারটিকে ব্যবহারকারীর নাম হিসাবে আখ্যায়িত করব।
অ্যান্টনি জি - মনিকার পক্ষে ন্যায়বিচার

1
নেই POSIX একটি ইউজার আইডি প্রয়োজন একটি ব্যবহারকারীর নাম যুক্ত করা এ সব ? রুট হিসাবে চলমান যে কোনও প্রোগ্রাম কল করতে পারে এবং কোনও ব্যবহারকারীর ডাটাবেসের অংশ হতে পারে setuid(some_id)এমন কোনও প্রয়োজন নেই some_id। লিনাক্সে ব্যবহারকারীর নেমস্পেসের মতো জিনিসগুলির সাথে এটি আপনার স্ক্রিপ্টগুলির জন্য পঙ্গু ধারণা হতে পারে।
মোশি

1
@ ফিলিপোস getpwuid()যা ফাংশনটি কল করার একটি ব্যয়বহুল পদ্ধতির মতো বলে মনে হয় যা lsনামগুলি লগইন করতে ইউআইডি অনুবাদ করে। গিলসের উত্তর এটি অর্জনের আরও প্রত্যক্ষ এবং দক্ষ উপায়।
অ্যান্টনি জি -

উত্তর:


14

এটি করার একটি সাধারণ উপায় হ'ল আপনি যা প্রোগ্রামটি চান তা বিদ্যমান রয়েছে এবং এটি আপনার থেকে পাওয়া যায় কিনা তা পরীক্ষা করা PATH। উদাহরণ স্বরূপ:

get_username(){
  uid="$1"

  # First try using getent
  if command -v getent > /dev/null 2>&1; then 
    getent passwd "$uid" | cut -d: -f1

  # Next try using the UID as an operand to id.
  elif command -v id > /dev/null 2>&1 && \
       id -nu "$uid" > /dev/null 2>&1; then
    id -nu "$uid"

  # Next try perl - perl's getpwuid just calls the system's C library getpwuid
  elif command -v perl >/dev/null 2>&1; then
    perl -e '@u=getpwuid($ARGV[0]);
             if ($u[0]) {print $u[0]} else {exit 2}' "$uid"

  # As a last resort, parse `/etc/passwd`.
  else
      awk -v uid="$uid" -F: '
         BEGIN {ec=2};
         $3 == uid {print $1; ec=0; exit 0};
         END {exit ec}' /etc/passwd
  fi
}

যেহেতু পক্সিক্স idইউআইডি আর্গুমেন্টকে সমর্থন করে না, এর elifজন্য এই ধারাটি idকেবলমাত্র idপ্যাথএইচটিতে রয়েছে কিনা তা পরীক্ষা করতে হবে, তবে এটি ত্রুটি ছাড়াই চলবে কিনা তাও পরীক্ষা করতে হবে। এর অর্থ এটি idদ্বিগুণ চলতে পারে , যা ভাগ্যক্রমে পারফরম্যান্সের উপর লক্ষণীয় প্রভাব ফেলবে না। এটাও সম্ভব উভয় idএবং awkএকই তুচ্ছ কর্মক্ষমতা হিট সঙ্গে, চালানো হবে।

বিটিডাব্লু, এই পদ্ধতিটির সাথে আউটপুট সংরক্ষণ করার দরকার নেই। তাদের মধ্যে একটি চালানো হবে, সুতরাং ফাংশনটি ফিরতে কেবলমাত্র একজন আউটপুট মুদ্রণ করবে।


একই ইউআইডি থাকার একাধিক ব্যবহারকারীর নাম সম্ভাবনা সঙ্গে মানিয়ে নিতে, থেকে সবকিছু মোড়ানো ifকরার fiমধ্যে { ... } | head -n 1। অর্থাত্ প্রথম uid ম্যাচ বাদে সমস্ত বাদ দিন। তবে এর অর্থ হ'ল আপনাকে যা প্রোগ্রাম চালিয়ে গেছে তার প্রস্থান কোড ক্যাপচার করতে হবে।
কাস

উত্তর করার জন্য ধন্যবাদ. আমি আশা করছিলাম যে আরও কিছু ইউটিলিটি থাকতে পারে যা আমি আগে আসেনি তবে এটি সহায়ক। যেহেতু আমার idকোনও আইডি অপারেন্ড হিসাবে গ্রহণ করে না এমন বাস্তবায়নে আমার অ্যাক্সেস নেই, তাই আমি বুঝতে পেরেছিলাম যে এর প্রস্থান স্থিতি পরীক্ষা করা সমস্যাযুক্ত হতে পারে - লগইন নাম বা ইউআইডির মধ্যে পার্থক্য কীভাবে বলা যায় যে অস্তিত্ব নেই। লগইন নামের পক্ষে কেবলমাত্র সংখ্যাসূচক অক্ষর থাকা সম্ভব: gnu.org/software/coreutils/manual/html_node/…
অ্যান্টনি জি - মনিকার পক্ষে ন্যায়বিচার

1
প্রতিটি সম্পাদনার সাথে সাথে ফাংশনটি আরও দৃ becoming় হয়ে উঠছে। :) এই নোটে, আমি সম্ভবত এই সুযোগগুলি আলাদা পথ আছে যে অফ-সুযোগের if command -v getent >/dev/null;পরিবর্তে ব্যবহার করব if [ -x /usr/bin/getent ] ;
অ্যান্টনি জি - মনিকার পক্ষে ন্যায়বিচার

3
হ্যাঁ। আমি নিয়মিত command -vএই উদ্দেশ্যে ব্যবহার করি : pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html (যদিও আমি কেবল এটি dashশেল বিল্টিন দিয়ে পরীক্ষা করেছি )।
অ্যান্টনি জি - মনিকার পক্ষে ন্যায়বিচার

1
@ অ্যান্থনি জিওগেন যদি আপনাকে কখনও প্রাচীন সিস্টেমে type foo >/dev/null 2>/dev/nullকাজ করতে হয় তবে আমি দেখেছি এমন প্রতিটি কাজ করে। commandতুলনামূলকভাবে আধুনিক।
গিলস 21

6

পসিক্সে এমন কিছু নেই যা অন্যকে সহায়তা করবে id। অনুশীলন করার সাথে সাথে চেষ্টা করে idআবার পার্সিংয়ে ফিরে যাওয়া /etc/passwdসম্ভবত বহনযোগ্য।

বুসিবক্স idব্যবহারকারী আইডি গ্রহণ করে না, তবে বুসিবক্স সহ সিস্টেমগুলি সাধারণত স্বায়ত্তশাসিত এম্বেডেড সিস্টেম যেখানে পার্সিং /etc/passwdযথেষ্ট।

আপনি যদি এমন idকোনও জিএনইউ ব্যবস্থাপনার মুখোমুখি না হন যেখানে ব্যবহারকারী আইডি গ্রহণ করে না, আপনি getpwuidপার্লের মাধ্যমে কল করার চেষ্টা করতে পারেন যে সুযোগটি পাওয়া যায়:

username=$(perl -e 'print((getpwuid($ARGV[0]))[0])) 2>/dev/null
if [ -n "$username" ]; then echo "$username"; return; fi

বা পাইথন:

if python -c 'import pwd, sys; print(pwd.getpwuid(int(sys.argv[1]))).pw_name' 2>/dev/null; then return; fi

2
পার্সিং /etc/passwdমোটেও পোর্টেবল নয় এবং এলডিএপি-এর মতো নন-পাসউইডি-ফাইল ব্যাকেন্ডের জন্য কাজ করবে না।
আর ..

আমার এমন কিছু, আমি এটা চুরি করব
CA গুলির

1
@ আর .. প্রশ্নকারী এটি সম্পর্কে সচেতন, এই উত্তরটি অন্যথায় দাবি করে না, সুতরাং আপনার মন্তব্যের মূল বক্তব্য কী?
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

এই উত্তরের জন্য ধন্যবাদ। আমি আশ্বস্ত হয়েছি যে অন্য কোনও ইউটিলিটি নেই যা সম্পর্কে আমি অবগত ছিলাম না। দেখে মনে হচ্ছে পসিআইএক্স একটি লগইন নামেরে ইউআইডি অনুবাদ করার জন্য একটি স্ট্যান্ডার্ড সি ফাংশন নির্দিষ্ট করে তবে প্রয়োজনীয় কমান্ডটি (অন্যটি ছাড়া id) নয়।
অ্যান্টনি জি -

2
শেষ ফলব্যাক হিসাবে, সিস্টেমে এসি সংকলক রয়েছে কিনা তা পরীক্ষা করে দেখুন, তবে সরবরাহিত
গেটপুইউইড

5

পসআইএক্স getpwuidএকটি আইডির লগইন নামের সাথে অনুবাদ করতে মঞ্জুর করে এমন একটি আইডি ব্যবহারকারীর ডাটাবেস অনুসন্ধান করার জন্য একটি স্ট্যান্ডার্ড সি ফাংশন হিসাবে নির্দিষ্ট করে । আমি গনুহ জন্য সোর্স কোড ডাউনলোড করা coreutils এবং এই ফাংশন যেমন ইউটিলিটি তাদের বাস্তবায়ন ব্যবহৃত হচ্ছে দেখতে পারেন idএবং ls

একটি শেখার অনুশীলন হিসাবে, আমি এই ফাংশনটির জন্য মোড়কের কাজটি করার জন্য এই দ্রুত এবং নোংরা সি প্রোগ্রামটি লিখেছিলাম। মনে রাখবেন যে আমি কলেজ থেকে সিতে প্রোগ্রামিং করি নি (অনেক বছর আগে) এবং এটি প্রযোজনায় ব্যবহার করার ইচ্ছা আমার নেই তবে আমি ভেবেছিলাম ধারণাটির প্রমাণ হিসাবে এটি এখানে পোস্ট করব (যদি কেউ এটি সম্পাদনা করতে চায় তবে) , মুক্ত মনে):

#include <stdio.h>
#include <stdlib.h>  /* atoi */
#include <pwd.h>

int main( int argc, char *argv[] ) {
    uid_t uid;
    if ( argc >= 2 ) {
        /* NB: atoi returns 0 (super-user ID) if argument is not a number) */
        uid = atoi(argv[1]);
    }
    /* Ignore any other arguments after the first one. */
    else {
        fprintf(stderr, "One numeric argument must be supplied.\n");
        return 1;
    }

    struct passwd *pwd;
    pwd = getpwuid(uid);
    if (pwd) {
        printf("The login name for %d is: %s\n", uid, pwd->pw_name);
        return 0;
    }
    else {
        fprintf(stderr, "Invalid user ID: %d\n", uid);
        return 1;
    }
}

এনআইএস / এলডিএপি দিয়ে এটি পরীক্ষা করার সুযোগ আমার ছিল না তবে আমি লক্ষ্য করেছি যে একই ব্যবহারকারীর জন্য যদি একাধিক এন্ট্রি থাকে /etc/passwdতবে এটি প্রথমটি বাদ দিয়ে সমস্ত উপেক্ষা করে।

ব্যবহারের উদাহরণ:

$ ./get_user ""
The login name for 0 is: root

$ ./get_user 99
Invalid user ID: 99

3

সাধারণত, আমি এটি করার বিরুদ্ধে সুপারিশ করব। ব্যবহারকারীর নাম থেকে ইউডে ম্যাপিং এক-এক-এক নয়, এবং এনকোডিং অনুমানগুলি যে আপনি একটি ব্যবহারকারীর নাম পেতে ইউড থেকে ফিরে রূপান্তর করতে পারেন তা ভেঙে যাচ্ছে। উদাহরণ হিসেবে বলা যায়, আমি প্রায়ই করে সম্পূর্ণরূপে রুট-মুক্ত ব্যবহারকারী-নামস্থান পাত্রে চালানো passwdএবং groupধারক আইডি 0 সমস্ত ব্যবহারকারী এবং গ্রুপ নাম মানচিত্রে ফাইল; এটি প্যাকেজ ইনস্টল করার chownব্যর্থতা ছাড়াই কাজ করতে দেয়। তবে যদি কোনও 0 0 কে একটি ইউডে রূপান্তরিত করার চেষ্টা করে এবং যা প্রত্যাশা করে তা না পেয়ে, এটি কৃত্রিমভাবে ভেঙে যায়। সুতরাং এই উদাহরণে, পরিবর্তিত হয়ে ব্যবহারকারী নামগুলি তুলনা করার পরিবর্তে আপনাকে ইউডে রূপান্তর করা উচিত এবং সেই জায়গার সাথে তুলনা করা উচিত।

আপনার যদি সত্যিই এই অপারেশনটি করার দরকার হয় তবে আপনি যদি মূল হন তবে একটি টেম্পল ফাইল তৈরি করে, chownএটি ইউআইডি-তে যুক্ত করে, তারপরে lsআবার পড়তে এবং মালিকের নামটি বিশ্লেষণ করে আংশিক পোর্টেবল করা সম্ভব might তবে আমি কেবল একটি সুপরিচিত পদ্ধতির ব্যবহার করব যা মানক নয় তবে "ব্যবহারের ক্ষেত্রে বহনযোগ্য" যেমন আপনি ইতিমধ্যে খুঁজে পেয়েছেন তার মধ্যে একটির মতো।

কিন্তু আবার, এটি করবেন না। কখনও কখনও কিছু করা শক্ত হওয়ায় আপনাকে বার্তা পাঠানো হয়।


1
মন্তব্য মুছে ফেলা। আমি উভয় অংশগ্রহণকারীদের মনে করিয়ে দিতে চাই যে মন্তব্যগুলি সিভিল হওয়া উচিত।
terdon
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.