লিনাক্স আইও প্রতি ফাইল মনিটরিং?


29

আমি সেন্টোস-এ ফাইল প্রতি ফাইল ডিস্ক নিরীক্ষণের জন্য কোনও ইউটিলিটি বা প্রক্রিয়াতে আগ্রহী ।

উইন ২০০৮-এ, রেসমন ইউটিলিটি এই ধরণের ড্রিলডাউন করার অনুমতি দেয় তবে আমি যে লিনাক্স ইউটিলিটিগুলি পেয়েছি তার মধ্যে এটির কোনওটিই (আইওস্যাট, আইওটপ, ডিস্ট্যাট, এনমন) করতে পারে না।

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



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

@ ম্যাট তবে একটি কার্যকর উত্তর দিয়ে!
ew white

উত্তর:


18

সিস্টেমট্যাপ সম্ভবত আপনার সেরা বিকল্প।

এখানে iotime.stp উদাহরণ থেকে আউটপুটটি কেমন দেখাচ্ছে:

825946 3364 (NetworkManager) access /sys/class/net/eth0/carrier read: 8190 write: 0
825955 3364 (NetworkManager) iotime /sys/class/net/eth0/carrier time: 9
[...]
117061 2460 (pcscd) access /dev/bus/usb/003/001 read: 43 write: 0
117065 2460 (pcscd) iotime /dev/bus/usb/003/001 time: 7
[...]
3973737 2886 (sendmail) access /proc/loadavg read: 4096 write: 0
3973744 2886 (sendmail) iotime /proc/loadavg time: 11

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

বা যদি আপনি অধৈর্য হন, অধ্যায় 4 দেখুন দেখুন শিক্ষানবিশদের গাইড থেকে দরকারী সিস্টেমট্যাপ স্ক্রিপ্ট


17

সিস্টেমট্যাপ * স্ক্রিপ্ট:

#!/usr/bin/env stap
#
# Monitor the I/O of a program.
#
# Usage:
#   ./monitor-io.stp name-of-the-program

global program_name = @1

probe begin {
  printf("%5s %1s %6s %7s %s\n",
         "PID", "D", "BYTES", "us", "FILE")
}

probe vfs.read.return, vfs.write.return {
  # skip other programs
  if (execname() != program_name)
    next

  if (devname=="N/A")
    next

  time_delta = gettimeofday_us() - @entry(gettimeofday_us())
  direction = name == "vfs.read" ? "R" : "W"

  # If you want only the filename, use
  // filename = kernel_string($file->f_path->dentry->d_name->name)
  # If you want only the path from the mountpoint, use
  // filename = devname . "," . reverse_path_walk($file->f_path->dentry)
  # If you want the full path, use
  filename = task_dentry_path(task_current(),
                              $file->f_path->dentry,
                              $file->f_path->mnt)

  printf("%5d %1s %6d %7d %s\n",
         pid(), direction, $return, time_delta, filename)
}

আউটপুটটি দেখতে এটির মতো দেখাচ্ছে:

[root@sl6 ~]# ./monitor-io.stp cat
PID D  BYTES      us FILE
3117 R    224       2 /lib/ld-2.12.so
3117 R    512       3 /lib/libc-2.12.so
3117 R  17989     700 /usr/share/doc/grub-0.97/COPYING
3117 R      0       3 /usr/share/doc/grub-0.97/COPYING

অথবা আপনি যদি মাউন্টপয়েন্ট থেকে কেবল পথ প্রদর্শন করতে চান:

[root@f19 ~]# ./monitor-io.stp cat
  PID D  BYTES      us FILE
26207 R    392       4 vda3,usr/lib64/ld-2.17.so
26207 R    832       3 vda3,usr/lib64/libc-2.17.so
26207 R   1758       4 vda3,etc/passwd
26207 R      0       1 vda3,etc/passwd
26208 R    392       3 vda3,usr/lib64/ld-2.17.so
26208 R    832       3 vda3,usr/lib64/libc-2.17.so
26208 R  35147      16 vdb7,ciupicri/doc/grub2-2.00/COPYING
26208 R      0       2 vdb7,ciupicri/doc/grub2-2.00/COPYING

[root@f19 ~]# mount | grep -E '(vda3|vdb7)'
/dev/vda3 on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/vdb7 on /mnt/mnt1/mnt11/data type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

সীমাবদ্ধতা / বাগ:

  • এমএমএপ ভিত্তিক আই / ও devnameহ'ল না কারণ এটি"N/A"
  • tmpfs এ ফাইলগুলি প্রদর্শিত হয় না কারণ devnameএটি"N/A"
  • পঠনগুলি ক্যাশে থেকে এসেছে বা লেখাগুলি বাফারের কাছে আসে তা বিবেচ্য নয়

ম্যাথু ইফির প্রোগ্রামগুলির ফলাফল :

  • জন্য mmaptest ব্যক্তিগত:

     PID D  BYTES      us FILE
    3140 R    392       5 vda3,usr/lib64/ld-2.17.so
    3140 R    832       5 vda3,usr/lib64/libc-2.17.so
    3140 W     23       9 N/A,3
    3140 W     23       4 N/A,3
    3140 W     17       3 N/A,3
    3140 W     17     118 N/A,3
    3140 W     17     125 N/A,3
    
  • জন্য mmaptest ভাগ করেছে:

     PID D  BYTES      us FILE
    3168 R    392       3 vda3,usr/lib64/ld-2.17.so
    3168 R    832       3 vda3,usr/lib64/libc-2.17.so
    3168 W     23       7 N/A,3
    3168 W     23       2 N/A,3
    3168 W     17       2 N/A,3
    3168 W     17      98 N/A,3
    
  • ডায়োস্টেস্টের জন্য (সরাসরি আই / ও):

     PID D  BYTES      us FILE
    3178 R    392       2 vda3,usr/lib64/ld-2.17.so
    3178 R    832       3 vda3,usr/lib64/libc-2.17.so
    3178 W     16       6 N/A,3
    3178 W 1048576     509 vda3,var/tmp/test_dio.dat
    3178 R 1048576     244 vda3,var/tmp/test_dio.dat
    3178 W     16      25 N/A,3
    

* RHEL 6 বা সমমানের জন্য দ্রুত সেটআপের নির্দেশাবলী: yum install systemtapএবং instructionsdebuginfo-install kernel


ঠিক সেখানে কিছু চমত্কার চিত্তাকর্ষক সিস্টেমট্যাপ রয়েছে। এর বহুমুখিতাটির একটি দুর্দান্ত প্রদর্শন।
ম্যাথু ইফে

এই পরিমাপটি কি I / O এবং অ্যাসিক্রোনাস আই / ওকে সরাসরি পরিচালনা করে? (io_submit ব্যবহার করে, পিক্সিক্স নয়)
ম্যাথু ইফ

@ মিলফ: ধন্যবাদ! পার্শ্ব দ্রষ্টব্য হিসাবে, স্ক্রিপ্টটি লেখার সময় আমি পিভিতে একটি ছোট্ট বাগ এবং সিস্টেমট্যাপে অন্য একটি আবিষ্কার করতে সক্ষম হয়েছিল ( task_dentry_path) :-): আমি / ও সম্পর্কে আমার কোনও ধারণা নেই তবে আপনি যদি আমাকে কোন আদেশ দেন বা আমি এটি পরীক্ষা করতে পারি একটি নমুনা প্রোগ্রাম। উদাহরণস্বরূপ আমি পাইথনকে এমএমএপ পরীক্ষার জন্য ব্যবহার করেছি । dd iflag=direct oflag=directদেখায়.
ক্রিশ্চিয়ান সিউপিতু

2
এমএমএ্যাপের জন্য এটি ব্যবহার করে দেখুন: gist.github.com/anonymous/7014284 আমি বাজি দিচ্ছি যে ব্যক্তিগত ম্যাপিংগুলি পরিমাপ করা হয় না তবে ভাগ করে নেওয়া হয় ..
ম্যাথু আইফে

2
তিনি সরাসরি আইও পরীক্ষা করেছেন: gist.github.com/anonymous/7014604
ম্যাথু

9

আপনি আসলে এটির জন্য ব্যবহার করতে চান blktraceসিকওয়াতচার এবং ব্লকট্রেসের সাথে লিনাক্স আইও ভিজুয়ালাইজিং দেখুন ।

আমি শীঘ্রই আমার একটি উদাহরণ পোস্ট করতে পারি কিনা তা আমি দেখতে পাচ্ছি।


সম্পাদনা:

আপনি লিনাক্সের বিতরণের কথা উল্লেখ করেন না , তবে আপনি যদি RHEL- জাতীয় সিস্টেম ব্যবহার করেন তবে লিনাক্স বা এমনকি সিস্টেম ট্যাপে কোনও dtrace স্ক্রিপ্টের পক্ষে এটি খুব ভাল ।


2
ধন্যবাদ, ভাল জিনিস এবং বিন্দুর খুব কাছাকাছি, তবে এটি বিস্তারিত ব্লক-স্তর তথ্য সরবরাহ করে, আমার এমন কিছু দরকার যা ভিএফএস বিমূর্ত স্তরটিতে কাজ করে।
জিওম্যাক

আমি এই চলমান পেতে কিছু সিস্টেমট্যাপ স্ক্রিপ্ট চেষ্টা করতে শুরু করেছি। সার্ভার ক্র্যাশ হওয়ার কারণে আমি ব্যর্থ হয়েছি। আমি সোলারিসে ডিট্রেস-এ এই তথ্যটি পেতে পারি। আমি আজ লিনাক্স দিয়ে চেষ্টা করব।
ew white

4

আমি কেবলমাত্র সেই সরঞ্জামটিই জানি যা ফাইল দ্বারা আই / ও ক্রিয়াকলাপ পর্যবেক্ষণ করতে পারে inotifywatch। এটি inotify-toolsপ্যাকেজের অংশ । দুর্ভাগ্যক্রমে, এটি কেবল আপনাকে অপারেশন গণনা দেয়।


4

উচ্চ আইও অবদান রাখে এমন প্রসেসের পিআইডি পেতে আইটপ ব্যবহার করুন

আপনি যে পিআইডি তৈরি করেছেন তার বিরুদ্ধে স্ট্রেস চালান, আপনি দেখতে পাবেন কোন নির্দিষ্ট প্রক্রিয়া দ্বারা কোন ফাইল অ্যাক্সেস করা হচ্ছে

strace -f -p $PID -e trace=open,read,write

স্ট্রেস সিস্কলগুলি এবং অ্যাক্সেস করা ফাইলগুলির তথ্য সরবরাহ করবে, পার্স করা এবং ব্যবহারের পরিসংখ্যান পাওয়া খুব কঠিন হবে ...
জিওম্যাক

1
ভেবেছিলাম আমি এটি চেষ্টা করব এটি প্রচুর ডেটা উত্পন্ন করে। এবং প্রক্রিয়াটি ক্র্যাশ করতে পারে যখন আপনি ctrl + c। এটি বরং বিপজ্জনক বলে মনে হচ্ছে।
ম্যাট

4

আমি শেষ পর্যন্ত এর জন্য সিসডিগ ব্যবহার করেছি


কীভাবে করবেন: সিসডিগ ইনস্টল করুন , চালান csysdig, এফ 2 টিপুন এবং দেখুন নির্বাচন করুন Files। আপনি ওপিএস কলাম দ্বারা অ্যাক্সেস করা ফাইলগুলির শীর্ষগুলি দেখতে পাবেন (F9 টিপতে পরিবর্তন করা যেতে পারে)।
catpnosis

csysdig -v filesসরাসরি "ফাইলগুলি" ভিউতে যান
জার্ট ভ্যান ড্যান বার্গ

2

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

আরও আকর্ষণীয় হতে পারে তা হল আপনি নিজেরাই ডিস্কগুলিতে দীর্ঘ সময়ের জন্য অপেক্ষা করছেন কিনা। আপনি "কलेक्टেল-এসডি" কমান্ডের মাধ্যমে সংগ্রহের মাধ্যমে এটি করতে পারেন যা পৃথক ডিস্কের পারফরম্যান্সের পরিসংখ্যান দেখায়। কি - এটিকে শীর্ষ-মতো ইউটিলিটিতে পরিণত করতে। যদি প্রচুর ডিস্ক জড়িত থাকে তবে এটি কলমাক্সের মাধ্যমে চালান: কলমাক্স -কম্যান্ড "-এসডি" এবং এটি আপনাকে একাধিক সিস্টেমে এমনকি আপনার পছন্দসই কলাম অনুসারে বাছাই করতে দেয়।


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

এটি সঠিক প্রশ্ন; লক্ষ্যটি সনাক্ত করার চেষ্টা করছে "কোন টেবিলটি এই আই / ও এর সাথে সংঘটিত হচ্ছে?" এবং বেশিরভাগ ডাটাবেসে একটি টেবিলটি এক বা একাধিক ফাইল। কোনও ডিস্ক এতে অনেকগুলি ফাইলের সমাপ্ত হতে চলেছে এবং হটস্পটগুলির মধ্যে কোনটি নির্ধারণ করা একটি দরকারী ডাটাবেস টিউনিং ইনপুট।
গ্রেগ স্মিথ

2

আপনি I / O প্রতি ব্লক ডিভাইস নিরীক্ষণ করতে পারেন (মাধ্যমে জন্য / proc / diskstats) এবং প্রক্রিয়া প্রতি (মাধ্যমে অ্যাকাউন্টিং IO /proc/$PID/ioবা taskstats ), কিন্তু আমি প্রতি ফাইল এটা করতে একটি উপায় জানি না।


0

হতে inotify এই সমস্যার সমাধানের সমাধান হবে।

ইনোটিফাই এআইপি ফাইল সিস্টেম ইভেন্টগুলি পর্যবেক্ষণের জন্য একটি প্রক্রিয়া সরবরাহ করে not চিহ্নিত করুন পৃথক ফাইলগুলি নিরীক্ষণ করতে বা ডিরেক্টরিগুলি নিরীক্ষণের জন্য ব্যবহার করা যেতে পারে। যখন কোনও ডিরেক্টরি পর্যবেক্ষণ করা হয়, তখন ইনোটিফাই ডিরেক্টরিটি এবং ডিরেক্টরিতে থাকা ফাইলগুলির জন্য ইভেন্টগুলি ফিরিয়ে দেয়।

ইনোটাইফাই সহ ফাইল সিস্টেমের ক্রিয়াকলাপ পর্যবেক্ষণ করুন

রেফারেন্স inotify


এটি ফাইলটিতে করা কলগুলি সরবরাহ করতে পারে তবে পিড এটি কী করেছে, কত বড় লেখাটি ছিল, কোথায় এবং কতক্ষণ লেগেছে তা আবিষ্কার করতে সহায়তা করার জন্য খুব কম প্রস্তাব দেয়।
ম্যাথু ইফি

প্রশ্নটি প্রক্রিয়াটি সম্পর্কে জিজ্ঞাসা করে না (এটি সম্ভবত অন্যান্য উপায়ে যেমন আবিষ্কার করা যেতে পারে lsof)
গার্ট ভ্যান ডান বার্গ

0

উত্তরগুলিতে এখানে প্রচুর ভাল তথ্য থাকা সত্ত্বেও আমি ভাবছি এটি বাস্তবায়িত কিনা?

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

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

এমএমপড ফাইলগুলির জন্য আমি সবচেয়ে ভাল বিবেচনা করতে পারি, এটি যদি আপনার পক্ষে কার্যকর হয় তবে হ'ল আগ্রহের প্রতিটি ফাইলকে আলাদা ডিভাইসে রেখে দেওয়া এবং আপনার ব্যবহারের তথ্য সংগ্রহ করার জন্য ডিভাইসের পরিসংখ্যান ব্যবহার করা। আপনি এই জন্য lvm পার্টিশন ব্যবহার করতে পারেন। একটি বাইন্ড মাউন্ট কাজ করবে না যদিও এটি একটি নতুন ব্লক ডিভাইস তৈরি করে না।

একবার আপনার পৃথক ব্লক ডিভাইসে আপনার ফাইলগুলি উপস্থিত থাকলে আপনি / sys / block / *, বা / proc / ডিস্কস্ট্যাট থেকে স্ট্যাটাস পেতে পারেন

এটি একটি প্রোডাকশন সার্ভারের সাথে পরিচয় করিয়ে দেওয়া খুব বিঘ্নজনক হতে পারে তবে আপনি এটি ব্যবহার করতে পারেন।

যদি ফাইলগুলি ম্যাপ করা না থাকে, তবে হ্যাঁ, আপনি এখানে অন্য যে কোনও সমাধান বেছে নিতে পারেন।


সাবধানে পড়ুন, দয়া করে আমার ব্লক-স্তরের পরিসংখ্যানের দরকার নেই :)
জিওম্যাক

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

-1

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


1
সংগ্রাহক প্রতি ফাইল প্রতি নিরীক্ষণ করে না, এটি প্রক্রিয়া অনুযায়ী কাজ করে
গ্রেগ স্মিথ

-1

আমি আপনাকে http://dag.wieers.com/home-made/dstat/ চেক করার পরামর্শ দিচ্ছি । এই দুর্দান্ত সরঞ্জামটি প্রচুর পরিসংখ্যান পরীক্ষা করতে দেয়।


1
dstat প্রতি ফাইল প্রতি নিরীক্ষণ করে না, এটি প্রক্রিয়া অনুযায়ী সংক্ষিপ্তসার করে
গ্রেগ স্মিথ

-2

আমি মনে করি যে আইওটিতে বাধা চিহ্নিত করার জন্য লিনাক্সের অন্যতম সেরা হাতিয়ার আইওটপ।


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